home *** CD-ROM | disk | FTP | other *** search
/ Just Call Me Internet / Just Call Me Internet.iso / prog / atari / m2 / cat3src / cat / grin.i < prev    next >
Text File  |  1997-10-26  |  157KB  |  4,564 lines

  1. IMPLEMENTATION MODULE grin;
  2.  
  3. (*==============================================================*
  4.  * Modul:               CAT-Anzeigemodul, neue Version          *
  5.  * Autor:               Johannes G”ttker-Schnetmann             *
  6.  * erstellt am:         19.10.1991                              *
  7.  * letzte Žnderung am:  06.01.1993                              *
  8.  * Version:             1.0                                     *
  9.  * Interne Version:     V#0010                                  *
  10.  *==============================================================*
  11.  
  12.  Anzeigemodul, beruhend auf dem CatEditor. Msgs werden als readonly-Texte
  13.  angezeigt.
  14.  
  15.   Die Strings fr Infozeile und Windowtitle werden schon in CatEdit
  16.   behandelt und gespeichert, deswegen muž das hier noch rausfliegen, 
  17.   um keinen Platz zu verschwenden.
  18.  
  19.  Probleme: Fensterposition, Datenstruktur evtl. verkleinern, siehe
  20.            Anmerkungen im Text;
  21.  
  22.  *----------------------------------------------------------------------------
  23.  * 19.10.91 0001  JGS    Erste Version
  24.  * 20.10.91       JGS    .. the endless story
  25.  * 22.12.91       JGS    Fensterlisten verbessert
  26.  * 23.12.91       JGS    Funktionsumfang erweitert, Erkennung ob Msg in
  27.  *                       gewnschte Richtung verfgbar, Debugging
  28.  * 16.02.92       JGS    Beginn Implementation der Infozeile
  29.  * 09.03.92 0002  JGS    Anpassung an CatTypes
  30.  * 25.03.92 0003  JGS    Neuer Windowdialog, normale Infozeile wird auch
  31.  *                       initialisiert
  32.  * 26.03.92       JGS    Features erweitert 27./
  33.  * 01.04.92       JGS    Flags setzen, auch ber einen Klick in die Box
  34.  * 02.04.92 0004  JGS    Status bei pers”nlichen Msgs
  35.  * 03.04.92       JGS    Gelesen-Bit automatisch setzen
  36.  * 04.04.92       JGS    Letzte Gelesene Msg/erste graphische Positionsanzeige/
  37.  *                       ctrl zus„tzlich ”ffnet neues Fenster
  38.  * 06.04.92 0005  JGS    Versuch, alle Aktionen in der Box unterzubringen:
  39.  *                       jetzt Popups..
  40.  * 08.06.92 0006  JGS    Zur n„chsten Gruppe mit neuen Nachrichten..
  41.  * 10.04.92 0007  JGS    Antworten/Kommentieren ber untergeordnetes Modul
  42.  * 12.04.92       JGS    Anpassung an neues handlePool, flexiblere Listen
  43.  * 16.04.92 0008  JGS    Richtige Reihenfolge beim Gruppenwechsel
  44.  * 19.04.92 0009  JGS    Suchen eingebaut
  45.  * 15.08.92       JGS    Bugfix Rckw„rts-suchen; Zuerst in Msg suchen, dann in Database
  46.  * 01.10.92       JGS    Einige kleinere Žnderungen wg. neuer Datenbank
  47.  * 17.12.92       DS     Einige Bugfixes und Žnderungen wegen Link zu MsgList     
  48.  * 27.12.92 0010  JGS    Flags werden jetzt direkt hier verwaltet, vorher in cat.m, popups
  49.  * 28.12.92       JGS    gruppenbergreifende Kommentare
  50.  * 29.12.92       JGS    Flag„nderungen in allen sichtbaren Msgs
  51.  * 31.12.92       JGS    Protokollunterstrzung, Baum "behandeln"
  52.  * 06.01.93       JGS    <undo> bei Msgs, verbessertes Handling bei Fehlern
  53.  * 12.08.93       JGS    Anzeige, ob Nachricht vom User oder Kommentar auf solche
  54.  * 30.09.93       JGS    Suchen nach Usenet-Verkettung
  55.  *----------------------------------------------------------------------------
  56.  *)
  57.  
  58. (*-- MM2-Module ------------------------------------------------------------*)
  59. FROM SYSTEM     IMPORT ADDRESS, ADR, TSIZE, CALLSYS, CADR, ASSEMBLER;
  60. FROM Storage    IMPORT ALLOCATE, DEALLOCATE, AllAvail;
  61. IMPORT Lists;
  62. IMPORT GrafBase;
  63. IMPORT BinOps;
  64. IMPORT Strings;
  65. IMPORT StrConv;
  66. IMPORT Block;
  67. FROM Characters      IMPORT CR, LF;
  68.  
  69. (*-- Cat-Module ------------------------------------------------------------*)
  70. FROM Void         IMPORT v;
  71. FROM UserInformation IMPORT UserBLK;
  72. FROM Messages   IMPORT SendState;
  73. FROM GroupComment IMPORT PrepareIDnGroup, PrepareID;
  74.  
  75. IMPORT data;
  76. IMPORT dataSys;
  77. IMPORT CatEdit;
  78. IMPORT EditTypes;
  79. IMPORT MTE;
  80. IMPORT VDIStandards;
  81. IMPORT VDIUtil;
  82. IMPORT MausTauschrsc;
  83. IMPORT CatTypes;
  84. IMPORT grinTools;
  85. IMPORT handlePool;
  86. IMPORT ZSearchDial;
  87. IMPORT SearchHelp;
  88. FROM SearchHelp IMPORT suchVar;
  89. IMPORT ConfVars;
  90. IMPORT msgList;
  91. IMPORT Varnames;
  92. IMPORT CatGlobal;
  93. IMPORT WdwManager;
  94. IMPORT ConvertDate;
  95. IMPORT ListHelp;
  96. IMPORT RectFuncs;
  97. IMPORT GroupSelect;
  98. IMPORT treeList;
  99. IMPORT AssFuncs;
  100. IMPORT GenderTest;
  101. IMPORT WiederVorlage;
  102. IMPORT Protokoll;
  103. IMPORT Clip;
  104.  
  105. (*-- Magic-Lib -------------------------------------------------------------*)
  106. IMPORT MagicStrings;
  107. IMPORT MagicAES;
  108. IMPORT MagicVDI;
  109. IMPORT MagicDOS;
  110. IMPORT MagicConvert;
  111.  
  112. (*-- Magic-Tools -----------------------------------------------------------*)
  113. IMPORT mtArea;
  114. IMPORT mtPopups;
  115. IMPORT mtUtils;
  116. IMPORT mtAlerts;
  117. IMPORT mtAppl;
  118. IMPORT WinDials;
  119.  
  120. CONST DEBUG = FALSE;
  121.  
  122. CONST oldInfoLine = TRUE;
  123. (* Das muž natrlich noch eine der globalen Variablen im catuser.inf werden *)
  124.  
  125. CONST openBracket = '('; 
  126.       closeBracket = ')'; 
  127.       spaceString = ' '; 
  128.       colonString = ':';
  129.       rawInfoline = '.... ---------- '; (* oder auch lfitdkbuuv? *)
  130.       
  131.       cMale      = "Herr";
  132.       cFemale    = "Frau";
  133.  
  134. CONST StateAnz = 9;
  135.  
  136. CONST escScan   = 1C;
  137.       spaceScan = 71C;
  138.       nullScan  = 160C;
  139.       pointScan = 161C;
  140.       oneScan   = 155C;
  141.       twoScan   = 156C;
  142.       threeScan = 157C;
  143.       fourScan  = 152C;
  144.       fiveScan  = 153C;
  145.       sixScan   = 154C;
  146.       eightScan = 150C;
  147.       undoScan  = 141C;
  148.       nScan     = 61C;
  149.       zScan     = 25C;
  150.       insertScan= 122C;
  151.       backspaceScan = 16C;
  152.       tabScan   = 17C;
  153.  
  154.       lScan = 46C; (* Gelesen-Flag      *)
  155.       fScan = 41C; (* Gefunden-Flag     *)
  156.       iScan = 27C; (* Interessant-Flag  *)
  157.       tScan = 24C; (* Teill”schen-Flag  *)
  158.       dScan = 40C; (* L”schen-Flag      *)
  159.       kScan = 45C; (* Kommentieren-Flag *)
  160.       bScan = 60C; (* Beantworten-Flag  *)
  161.       cScan = 56C; (* Userflag 1        *)
  162.       xScan = 55C; (* Userflag 2        *)
  163.       vScan = 57C; (* Vererben-Flag     *)
  164.  
  165. (* Zu jedem Fenster geh”rt eine folgende Struktur: *)
  166.  
  167. TYPE oneWindowPtr = POINTER TO oneWindow;
  168. TYPE headerInfoType = (headerNone, headerGruppe, headerFollowupTo, 
  169.                        headerID, headerKomZu, 
  170.                        headerBetreff, headerVon, headerSender, headerReplyTo, 
  171.                        headerName, headerAn, 
  172.                        headerMId, headerRId, headerMime, headerGate, 
  173.                        headerBox, headerStatus, headerKomAnz, 
  174.                        headerEmptyLine);
  175.  
  176. CONST maxStack = 1023;
  177. TYPE    viewHeaderMode = (vhNone, vhFull);
  178.  
  179. TYPE stackArrayType   = ARRAY[0..maxStack] OF CARDINAL;
  180. TYPE stackPointerType = POINTER TO stackArrayType;
  181. TYPE oneWindow =
  182.        RECORD
  183.          win     : INTEGER;            (* Zugeh”riges Fenster *)
  184.          handle  : handlePool.oneHandlePtr; (* Zeiger in die Datenbankhandleliste *)
  185.          mess    : data.MessageType;   (* Alle Daten zu einer Message *)
  186.          isEnriched: BOOLEAN;          (* Aktuelle Nachricht ist text/enriched *)
  187.          nextMsg : grinNextMessProc;   (* Kann von aufrufender Prozedur bei grinOpenMessage bergeben werden *)
  188.          listHdl : LONGCARD;           (*         "    *)
  189.          info,
  190.          title   : CatTypes.String255;
  191.          number  : INTEGER;
  192.          inObjcDraw : BOOLEAN;  (* Es wird gerade ein einzelnes Objekt neu gezeichnet *)
  193.          font,
  194.          fontSize   : INTEGER;
  195.          lastPos    : CARDINAL;  (* Fr <home> in der Kommentarverkettung *)
  196.          undoPos,
  197.          undoGroup,
  198.          undoTreeRoot : CARDINAL;  (* Fr <undo> bei Msgs *)
  199.          lastLine   : headerInfoType;
  200.          mode       : openMode;
  201.          readchange : BOOLEAN; (* hat der user etwas am Gelesen-Flag gemacht? *)
  202.          isLocked   : BOOLEAN; (* Fenster gelockt, da Suche l„uft oder „hnliches *)
  203.          inEvent    : BOOLEAN; (* Fenster behandelt gerade einen Click-Event *)
  204.          (* Fr's Baumlaufen: *)
  205.          treeMode     : BOOLEAN;
  206.          idx          : CARDINAL;
  207.          stack        : stackPointerType;
  208.          stackPointer : CARDINAL;
  209.          (* Fr SuppressRef *)
  210.          originalText : ADDRESS;
  211.          refSuppressed: BOOLEAN;
  212.          (* Fr Anzeige: *)
  213.          viewHeader   : viewHeaderMode;
  214.          viewBuff     : ADDRESS;
  215.          viewLen      : LONGCARD;
  216.          viewAllocated: BOOLEAN;
  217.          (* Fr Drag&Drop: *)
  218.          ddObjc       : INTEGER;
  219.        END;
  220.  
  221. (* Um Platz zu sparen, mžte in Zukunft m”glicherweise in data.MessageType
  222.  * eine flexible Verwaltung der 4 langen Strings erfolgen; aužerdem k”nnte
  223.  * man dann auch <info> und <title> flexibel gestalten
  224.  *)
  225.  
  226. TYPE NumSet  = SET OF [0..255];
  227.  
  228. VAR grinNums : NumSet;
  229.     globalNumber : INTEGER;
  230.  
  231. TYPE dirType = (dPrevMess, dNextMess, dUpMess, dDownMess, dLeftMess, dRightMess, dReturn, dJump, dGroupJump, dNone);
  232.  
  233. VAR windows : Lists.List;      (* Liste der offenen Fenster/Messages *)
  234. VAR infoAdr,
  235.     flagPop,
  236.     addInfo : POINTER TO ARRAY[0..MAX(CARDINAL)] OF MagicAES.OBJECT;
  237.     RefIdUnterdruecken : BOOLEAN;
  238.     restrictedMoves    : BOOLEAN;
  239.     spacePaging        : BOOLEAN;
  240.     isInSearch         : BOOLEAN;
  241.     autoNextGroup      : BOOLEAN;
  242.     autoNextPing       : BOOLEAN;
  243.  
  244. PROCEDURE stopSearch():BOOLEAN;
  245. VAR char, scan : CHAR; kstate : BITSET;
  246. BEGIN
  247.   RETURN VDIUtil.isKey(kstate, scan, char) & (char = 33C);
  248. END stopSearch;
  249.  
  250. TYPE intPtr = POINTER TO INTEGER;
  251. (*$A+,Z-*)
  252. PROCEDURE FindWinCond(e, i : ADDRESS):BOOLEAN;
  253. (* Abbruchprozedur, wie in <Lists> gefordert *)
  254. BEGIN
  255.   RETURN oneWindowPtr(e)^.win = intPtr(i)^
  256. END FindWinCond;
  257. (*$A=,Z=*)
  258.  
  259.  
  260. (*--- Zugriff auf die Datenbank -------------*)
  261.  
  262. CONST   cTo         = "To: ";
  263.         cFrom       = "From: ";
  264.         cGroup      = "Group: ";
  265.         cNewsgroups = "Newsgroups: ";
  266.         cSubject    = "Subject: ";
  267.         cMausId     = "Maus-ID: ";
  268.         cMausRef    = "Maus-Ref: ";
  269.         cMessageID  = "Message-ID: ";
  270.         cReferences = "References: ";
  271.         cDate       = "Date: ";
  272.         cStatusDate = "State: ";
  273.         cFollowup   = "Followup-To: ";
  274.         cReply      = "Reply-To: ";
  275.         cSender     = "Sender: ";
  276.         cOrganization = "Organization: ";
  277.         cGateway    = "Gateway: ";
  278.         cMime       = "MIME: ";
  279.         cDashs      = '------------------------------------------------------------------------' + CR+LF+0C;
  280.         cLineEnd    = CR+LF;
  281.         cTAB        = 011C;
  282.  
  283.         cContent    = 'Content-Type:';
  284.         cTextEnriched = 'text/enriched';
  285.         cCharset    = 'charset=';
  286.         cIso        = 'ISO-8859-1';
  287.  
  288. PROCEDURE CharInStr (REF pattern: ARRAY OF CHAR; 
  289.                      REF str: ARRAY OF CHAR): INTEGER;
  290.   VAR p, l, highP, i : INTEGER;
  291. BEGIN
  292.   p := 0;
  293.   l := LENGTH (str);
  294.   highP := LENGTH (pattern)-1;
  295.   WHILE p < l DO
  296.     FOR i := 0 TO highP DO
  297.       IF str[p] = pattern [i] 
  298.       THEN
  299.         RETURN p;
  300.       END;
  301.     END;
  302.     INC (p);
  303.   END;
  304.   RETURN -1;
  305. END CharInStr;
  306.  
  307. PROCEDURE BuildId (str: CatTypes.Str255Ptr; VAR id: ARRAY OF CHAR);
  308.   VAR quote: BOOLEAN;
  309. BEGIN
  310.   MagicStrings.Assign ("", id);
  311.   quote := FALSE;
  312.   IF (str # NIL) & (str^[0] # 0C)
  313.   THEN
  314.     IF (str^[0] # '<')
  315.     THEN
  316.       quote := TRUE;
  317.     END;
  318.     IF quote
  319.     THEN
  320.       MagicStrings.Append ("<", id);
  321.     END;
  322.     MagicStrings.Append (str^, id);
  323.     IF quote
  324.     THEN
  325.       MagicStrings.Append (">", id);
  326.     END;
  327.   END;
  328. END BuildId;
  329.  
  330. PROCEDURE BuildName (str1, str2: CatTypes.Str255Ptr; VAR name: ARRAY OF CHAR);
  331.   VAR quote: BOOLEAN;
  332. BEGIN
  333.   MagicStrings.Assign ("", name);
  334.   quote := FALSE;
  335.   IF (str2 # NIL) & (str2^[0] # 0C)
  336.   THEN
  337.     IF CharInStr ('!()<>@,;:\".[]', str2^) >= 0
  338.     THEN
  339.       quote := CharInStr ("()<>", str2^) < 0;
  340.     ELSE
  341.       quote := FALSE;
  342.     END;
  343.     IF quote
  344.     THEN
  345.       quote := str2^[0] # '"';
  346.     END;
  347.     IF quote 
  348.     THEN
  349.       MagicStrings.Append ('"', name);
  350.     END;
  351.     MagicStrings.Append (str2^, name);
  352.     IF quote 
  353.     THEN
  354.       MagicStrings.Append ('"', name);
  355.     END;
  356.   END;
  357.   IF str1 # NIL 
  358.   THEN 
  359.     IF (str2 # NIL) 
  360.      & (CharInStr ("()<>", str2^) < 0)
  361.     THEN
  362.       quote := (str1^[0] # '<') & (str1^[0] # '(');
  363.       IF LENGTH (name) > 0
  364.       THEN 
  365.         MagicStrings.Append (" ", name);
  366.       ELSE
  367.         quote := FALSE;
  368.       END;
  369.       IF quote
  370.       THEN
  371.         MagicStrings.Append ("<", name);
  372.       END;
  373.       MagicStrings.Append (str1^, name);
  374.       IF quote
  375.       THEN
  376.         MagicStrings.Append (">", name);
  377.       END;
  378.     ELSIF str2 = NIL
  379.     THEN
  380.       MagicStrings.Append (str1^, name);
  381.     END;
  382.   END;
  383. END BuildName;
  384.         
  385. PROCEDURE GetLength (str: CatTypes.Str255Ptr; REF lineId: ARRAY OF CHAR): CARDINAL;
  386. BEGIN
  387.   IF str = NIL THEN RETURN 0 END;
  388.   IF str^[0] = 0C THEN RETURN 0 END;
  389.   RETURN LENGTH (lineId) + LENGTH (str^);
  390. END GetLength;
  391.  
  392. PROCEDURE CopyItem (buff: CatTypes.LargeTextPtr; str: CatTypes.Str255Ptr; 
  393.                     REF lineId: ARRAY OF CHAR; VAR pos: LONGCARD);
  394.   VAR adr: ADDRESS;
  395. BEGIN
  396.   IF str = NIL THEN RETURN END;
  397.   IF str^[0] = 0C THEN RETURN END;
  398.   adr := buff + ADDRESS(pos);
  399.   IF LENGTH (lineId) > 0
  400.   THEN
  401.     Block.Copy (CADR(lineId), LENGTH (lineId), buff+ADDRESS(pos));
  402.     INC (pos, LENGTH (lineId));
  403.   END;
  404.   Block.Copy (str, LENGTH (str^), buff+ADDRESS(pos));
  405.   INC (pos, LENGTH (str^));
  406.   Block.Copy (CADR(cLineEnd), LENGTH(cLineEnd), buff+ADDRESS(pos));
  407.   INC (pos, LENGTH(cLineEnd));
  408. END CopyItem;
  409.  
  410. PROCEDURE ParseMime (orgText: CatTypes.BigTextPtr; newText: CatTypes.BigTextPtr; 
  411.                      VAR textLen: CARDINAL);
  412. VAR     idx, destIdx : CARDINAL;
  413.         ch           : CHAR;
  414.         i,
  415.         newLineCnt,
  416.         paramcount,
  417.         excerptCount,
  418.         noFill       : INTEGER;
  419.         token        : CatTypes.String255;
  420.         found        : BOOLEAN;     (* einzelne '-'-Zeile gefunden *)
  421.         excerptSet   : BOOLEAN;
  422.  
  423. BEGIN
  424.   (* Simpel-Parser basierend auf RFC 1563 
  425.    *)
  426.   paramcount := 0;
  427.   excerptCount := 0;
  428.   excerptSet := FALSE;
  429.   noFill := 0;
  430.   newLineCnt := 0;
  431.   idx := 0;
  432.   destIdx := 0;
  433.   
  434.   (* Erweiterung fr MausNet: *)
  435.   (* Erstmal nach LF'-'LF suchen, in der DB steht eh nur LF als Zeilenende drin *)
  436.   found := FALSE;
  437.   WHILE (idx < textLen) & ~found DO
  438.     IF (orgText^[idx] = '-') & (orgText^[idx+1] = LF)
  439.     THEN
  440.       IF (idx = 0) OR (orgText^[idx-1] = LF)
  441.       THEN
  442.         found := TRUE;
  443.         INC (idx, 2);
  444.       END;
  445.     ELSE
  446.       INC (idx);
  447.     END;
  448.   END;
  449.   IF ~found
  450.   THEN
  451.     idx := 0;
  452.   END;
  453.   (* Ende der Erweiterung fr MausNet *)
  454.   
  455.   WHILE idx < textLen DO
  456.     ch := orgText^[idx];
  457.     IF ch = '<'
  458.     THEN
  459.       IF newLineCnt = 1
  460.       THEN
  461.         newText^[destIdx] := ' ';
  462.         INC (destIdx);
  463.       END;
  464.       newLineCnt := 0;
  465.       INC (idx);
  466.       ch := orgText^[idx];
  467.       IF ch = '<'
  468.       THEN
  469.         IF paramcount <= 0
  470.         THEN
  471.           newText^[destIdx] := ch;
  472.           INC (destIdx);
  473.         END;
  474.       ELSE
  475.         i := 0;
  476.         WHILE (idx < textLen) & (ch # '>') DO
  477.           IF i < SIZE (token)
  478.           THEN
  479.             token[i] := CAP(ch);
  480.             INC (i);
  481.           END;
  482.           INC (idx);
  483.           ch := orgText^[idx];
  484.         END;
  485.         token[i] := 0C;
  486.         IF Strings.StrEqual (token, "PARAM")
  487.         THEN
  488.           INC (paramcount);
  489.         ELSIF Strings.StrEqual (token, "EXCERPT")
  490.         THEN
  491.           INC (excerptCount);
  492.           excerptSet := TRUE;
  493.         ELSIF Strings.StrEqual (token, "BOLD")
  494.            OR Strings.StrEqual (token, "/BOLD")
  495.         THEN
  496.           newText^[destIdx] := '*';
  497.           INC(destIdx);
  498.         ELSIF Strings.StrEqual (token, "ITALIC")
  499.            OR Strings.StrEqual (token, "/ITALIC")
  500.         THEN
  501.           newText^[destIdx] := '/';
  502.           INC(destIdx);
  503.         ELSIF Strings.StrEqual (token, "UNDERLINE")
  504.            OR Strings.StrEqual (token, "/UNDERLINE")
  505.         THEN
  506.           newText^[destIdx] := '_';
  507.           INC(destIdx);
  508.         ELSIF Strings.StrEqual (token, "NOFILL")
  509.         THEN
  510.           INC (noFill);
  511.         ELSIF Strings.StrEqual (token, "/PARAM")
  512.         THEN
  513.           DEC (paramcount);
  514.         ELSIF Strings.StrEqual (token, "/EXCERPT")
  515.         THEN
  516.           DEC (excerptCount);
  517.         ELSIF Strings.StrEqual (token, "/NOFILL")
  518.         THEN
  519.           DEC (noFill);
  520.         END  
  521.       END;
  522.     ELSE (* IF ch = '<' *)
  523.       IF paramcount > 0
  524.       THEN
  525.       ELSIF (ch = LF) & (noFill <= 0)
  526.       THEN
  527.         INC (newLineCnt);
  528.         IF newLineCnt > 1
  529.         THEN
  530.           newText^[destIdx] := ch;
  531.           INC(destIdx);
  532.           IF excerptCount > 0
  533.           THEN
  534.             FOR i := 1 TO excerptCount DO
  535.               newText^[destIdx] := ">";
  536.               INC(destIdx);
  537.             END;
  538.             excerptSet := FALSE;
  539.           END;
  540.         END;
  541.       ELSE
  542.         IF newLineCnt = 1
  543.         THEN
  544.           newText^[destIdx] := ' ';
  545.           INC(destIdx);
  546.         END;
  547.         newLineCnt := 0;
  548.         IF excerptSet
  549.         THEN
  550.           FOR i := 1 TO excerptCount DO
  551.             newText^[destIdx] := ">";
  552.             INC(destIdx);
  553.           END;
  554.           excerptSet := FALSE;
  555.         END;
  556.         newText^[destIdx] := ch;
  557.         INC(destIdx);
  558.       END;
  559.     END;
  560.     INC (idx);
  561.   END; (* WHILE *)
  562.   newText^[destIdx] := LF;
  563.   INC (destIdx);
  564.   newText^[destIdx] := 0C;
  565.   textLen := destIdx;   (* neue L„nge zuweisen *)
  566. END ParseMime;
  567.  
  568. PROCEDURE GetStatusText (state: CHAR; VAR status: ARRAY OF CHAR);
  569. BEGIN
  570.   CASE state OF
  571.     'N': MagicStrings.Assign ('Nicht gelesen', status); |
  572.     'Z': MagicStrings.Assign ('Zurckgestellt', status); |
  573.     'B': MagicStrings.Assign ('Beantwortet', status); |
  574.     'G': MagicStrings.Assign ('Gelesen', status); |
  575.     'W': MagicStrings.Assign ('Weitergegeben', status); |
  576.     'M': MagicStrings.Assign ('Mausnet', status); |
  577.     'A': MagicStrings.Assign ('Angekommen', status); |
  578.     'Y': MagicStrings.Assign ('Gateway angekommen', status); |
  579.     'K': MagicStrings.Assign ('Kopiert', status); |
  580.     'T': MagicStrings.Assign ('Im MausTausch', status); |
  581.   ELSE
  582.     MagicStrings.Assign ('Unbekannter Status', status);
  583.   END;
  584. END GetStatusText;
  585.  
  586. PROCEDURE GetOneMessage(ptr : oneWindowPtr; nr : CARDINAL):BOOLEAN;
  587. (* den zugeh”rigen Typ auffllen *)
  588. VAR z : CARDINAL;
  589.     uName,
  590.     gName   : CatTypes.String255;
  591.     pos     : LONGCARD;
  592.     cStart  : INTEGER;
  593.     cEnd    : INTEGER;
  594.     content : CatTypes.String255;
  595.     newText : CatTypes.BigTextPtr;
  596.     oldLen  : CARDINAL;
  597.     
  598. BEGIN
  599.   data.ReadMessage(ptr^.handle^.Zugriff, nr, ptr^.mess);
  600.   IF data.error = data.noError
  601.   THEN
  602.     WITH ptr^ DO
  603.       IF mess.Text # NIL
  604.       THEN
  605.         isEnriched := FALSE;
  606.         (* Jetzt MIME-Parser anwerfen *)
  607.         IF mess.mime # NIL
  608.         THEN
  609.           (* Content-type extrahieren, mžte eigentlich case-insensitiv sein *)
  610.           cStart := Strings.Pos (cContent, mess.mime^, 0);
  611.           IF cStart > 0
  612.           THEN 
  613.             cStart := cStart + INTEGER(LENGTH(cContent));
  614.             cEnd := Strings.Pos (";", mess.mime^, cStart);
  615.             IF cEnd < 0
  616.             THEN
  617.               cEnd := INTEGER(LENGTH (mess.mime^));
  618.             END;
  619.             Strings.Copy (mess.mime^, cStart, cEnd - cStart, content, v.bool);
  620.             (* Fhrende Leerzeichen abschneiden *)
  621.             Strings.DelLeadingBlanks (content);
  622.             (* Content-type prfen *)
  623.             IF AssFuncs.StrIequal (cTextEnriched, content)
  624.             THEN
  625.               isEnriched := TRUE;
  626.               (* Text kopieren und parsen *)
  627.               oldLen := mess.textLen + 2048;
  628.               ALLOCATE (newText, oldLen);
  629.               IF newText # NIL
  630.               THEN
  631.                 (* Wenn kein Speicher frei ist, dann zeigen wir 
  632.                  * das halt unver„ndert an
  633.                  *)
  634.                 ParseMime (mess.Text, newText, mess.textLen);
  635.                 DEALLOCATE (mess.Text, 0);
  636.                 mess.Text := newText;
  637.                 (* Speicherblock fr newText noch anpassen *)
  638.                 IF oldLen # mess.textLen
  639.                 THEN
  640.                   DEALLOCATE (mess.Text, oldLen - mess.textLen);
  641.                 END;
  642.               END;
  643.             END;
  644.           END;
  645.           cStart := Strings.Pos (cCharset, mess.mime^, 0);
  646.           IF cStart > 0
  647.           THEN 
  648.             cStart := cStart + INTEGER(LENGTH(cCharset));
  649.             cEnd := Strings.Pos (";", mess.mime^, cStart);
  650.             IF cEnd < 0
  651.             THEN
  652.               cEnd := INTEGER(LENGTH (mess.mime^));
  653.             END;
  654.             Strings.Copy (mess.mime^, cStart, cEnd - cStart, content, v.bool);
  655.             IF AssFuncs.StrIequal (cIso, content)
  656.             THEN
  657.               (* Umlaute wandeln *)
  658.               AssFuncs.WandleIso (mess.Text, mess.textLen);
  659.             END;
  660.           END;
  661.         END;
  662.       END;
  663.     END;
  664.     ptr^.refSuppressed := FALSE;
  665.     IF RefIdUnterdruecken & (ptr^.mess.up < dataSys.notSaved) &
  666.        (ptr^.mess.Text # NIL) & 
  667.        (ptr^.mess.Text^[0] = '-')  &
  668.        ((ptr^.mess.fromOther) OR (ptr^.mess.KommentierteID[0] = 0C)) THEN
  669.       (* Also wenn kein Dateifehler aufgetreten ist, eine Verkettung hergestellt     *)
  670.       (* wurde, in der ersten Zeile m”glicherweise eine Verkettung steht aber keine  *)
  671.       (* ID von der Maus geliefert wurde *)
  672.       (* Originalpointer merken *)
  673.       ptr^.originalText := ptr^.mess.Text;
  674.       ptr^.refSuppressed := TRUE;
  675.       WITH ptr^.mess DO 
  676.         REPEAT
  677.           INC(Text);
  678.           DEC(textLen);
  679.         UNTIL (Text^[0] = LF) OR (textLen = 0);
  680.         (* Ende der Zeile suchen *)
  681.         WHILE (Text^[0] = LF) & (textLen > 0) DO
  682.           INC(Text);
  683.           DEC(textLen);
  684.         END;
  685.       END (* WITH *);
  686.       (* Zeilenende und evtl. noch ein paar Leerzeilen berspringen *)
  687.     END;
  688.     (* Jetzt viewBuffer aufbauen *)
  689.     (* Gr”že feststellen *)
  690.     WITH ptr^ DO
  691.       IF mess.Text # NIL
  692.       THEN
  693.         (* Und jetzt nachsehen, ob wir den Header anzeigen oder nicht *)
  694.         viewLen := 0;
  695.         IF viewHeader = vhFull
  696.         THEN
  697.           (* Alle Headerinformationen:
  698.            * To: 
  699.            * From: "Dirk Steins" <dirk_steins@k2.maus.de>
  700.            * Newsgroups: 
  701.            * Subject: 
  702.            * Maus-ID: 
  703.            * Maus-Ref:
  704.            * Message-ID: <..>
  705.            * References: <...>
  706.            * Date: englisches Datum
  707.            * Date: englisches Datum
  708.            * Followup-To: 
  709.            * Reply-To: 
  710.            * Organization: ...
  711.            * Gateway: ...
  712.            * Mime: ...
  713.            * Statusdatum: ...
  714.            *)
  715.           WITH mess DO
  716.             INC (viewLen, GetLength (Empfaenger, cTo));
  717.             BuildName (Absender, name, uName);
  718.             INC (viewLen, GetLength (ADR(uName), cFrom));
  719.             IF Gruppe # dataSys.private
  720.             THEN
  721.               GroupSelect.GroupName (Gruppe, gName);
  722.               INC (viewLen, GetLength (ADR(gName), cNewsgroups));
  723.             END;
  724.             INC (viewLen, GetLength (Betreff, cSubject));
  725.             INC (viewLen, GetLength (MailID, cMausId));
  726.             INC (viewLen, GetLength (ADR(KommentierteID), cMausRef));
  727.             INC (viewLen, GetLength (mid, cMessageID));
  728.             INC (viewLen, GetLength (rid, cReferences));
  729.             (* Datum vorl„ufig, muž noch umgewandelt werden *)
  730.             INC (viewLen, GetLength (ADR(Datum), cDate));
  731.             IF (Gruppe = dataSys.private)
  732.                & (EigeneNachricht)
  733.             THEN
  734.               GetStatusText (Status, uName);
  735.               MagicStrings.Append (' (', uName);
  736.               MagicStrings.Append (StatusDatum, uName);
  737.               MagicStrings.Append (' Uhr)', uName);
  738.               INC (viewLen, GetLength (ADR(uName), cStatusDate));
  739.               (*
  740.               INC (viewLen, GetLength (ADR(StatusDatum), cStatusDate));
  741.               *)
  742.             END;
  743.  
  744.             INC (viewLen, GetLength (sender, cSender));
  745.             INC (viewLen, GetLength (replyTo, cReply));
  746.             INC (viewLen, GetLength (followupTo, cFollowup));
  747.             INC (viewLen, GetLength (box, cOrganization));
  748.             INC (viewLen, GetLength (gate, cGateway));
  749.             INC (viewLen, GetLength (mime, cMime));
  750.             INC (viewLen, LENGTH (cDashs)+4);
  751.             INC (viewLen, 40);
  752.           END;
  753.         END;
  754.         INC (viewLen, mess.textLen);
  755.         ALLOCATE (viewBuff, viewLen);
  756.         IF viewBuff = NIL
  757.         THEN
  758.           viewBuff := mess.Text;
  759.           viewLen := mess.textLen;
  760.           viewAllocated := FALSE;
  761.         ELSE
  762.           viewAllocated := TRUE;
  763.           (* Buffer alloziert, nun reinschreiben *)
  764.           pos := 0;
  765.           IF viewHeader = vhFull
  766.           THEN
  767.             WITH mess DO
  768.               (* Einzelne Items kopieren *)
  769.               CopyItem (viewBuff, Empfaenger, cTo, pos);
  770.               BuildName (Absender, name, uName);
  771.               CopyItem (viewBuff, ADR(uName), cFrom, pos);
  772.               CopyItem (viewBuff, sender, cSender, pos);
  773.               CopyItem (viewBuff, replyTo, cReply, pos);
  774.               IF Gruppe # dataSys.private
  775.               THEN
  776.                 GroupSelect.GroupName (Gruppe, gName);
  777.                 CopyItem (viewBuff, ADR(gName), cNewsgroups, pos);
  778.               END;
  779.               CopyItem (viewBuff, followupTo, cFollowup, pos);
  780.               CopyItem (viewBuff, Betreff, cSubject, pos);
  781.               CopyItem (viewBuff, MailID, cMausId, pos);
  782.               CopyItem (viewBuff, ADR(KommentierteID), cMausRef,pos);
  783.               BuildId (mid, uName);
  784.               CopyItem (viewBuff, ADR(uName), cMessageID, pos);
  785.               BuildId (rid, uName);
  786.               CopyItem (viewBuff, ADR(uName), cReferences, pos);
  787.               (* Datum vorl„ufig, muž noch umgewandelt werden *)
  788.               CopyItem (viewBuff, ADR(Datum), cDate, pos);
  789.               
  790.               CopyItem (viewBuff, box, cOrganization, pos);
  791.               CopyItem (viewBuff, gate, cGateway, pos);
  792.               CopyItem (viewBuff, mime, cMime, pos);
  793.  
  794.               IF (Gruppe = dataSys.private)
  795.                  & (EigeneNachricht)
  796.               THEN
  797.                 GetStatusText (Status, uName);
  798.                 MagicStrings.Append (' (', uName);
  799.                 MagicStrings.Append (StatusDatum, uName);
  800.                 MagicStrings.Append (' Uhr)', uName);
  801.                 CopyItem (viewBuff, ADR(uName), cStatusDate, pos);
  802.               END;
  803.               
  804.               CopyItem (viewBuff, CADR(cDashs), "", pos);
  805.             END;
  806.           END;
  807.           (* Text kopieren *)
  808.           Block.Copy (mess.Text, mess.textLen, viewBuff + ADDRESS(pos));
  809.           INC (pos, mess.textLen);
  810.           viewLen := pos;
  811.         END;
  812.       END;
  813.     END;
  814.   END;
  815.   (*$? DEBUG:
  816.   IF data.error # data.noError
  817.   THEN
  818.     CASE data.error OF
  819.       data.notFound : MTE.numAlert (INTEGER(nr), "[3][Nachricht & |nicht gefunden.][[Abbruch]");
  820.     | data.IOError  : MTE.numAlert (INTEGER(nr), "[3][I/O-Fehler bei|Nachricht &.][[Abbruch]");
  821.     | data.noMemErr : MTE.numAlert (INTEGER(nr), "[3][Nicht genug Speicher|bei Nachricht &.][[Abbruch]");
  822.     | data.crcError : MTE.numAlert (INTEGER(nr), "[3][CRC-Fehler bei|Nachricht &.][[Abbruch]");
  823.     | data.fileError: MTE.numAlert (INTEGER(nr), "[3][Datei-Fehler bei|Nachricht &.][[Abbruch]");
  824.     ELSE
  825.     END;
  826.   END;
  827.   *)
  828.   RETURN data.error = data.noError;
  829. END GetOneMessage;
  830.  
  831. (*--- Fr das Drucken des Headers -------------------------------*)
  832. PROCEDURE grinGetHeaderInfo (wdw : INTEGER; which : EditTypes.lineMode;
  833.                              VAR s : ARRAY OF CHAR) : BOOLEAN;
  834. (* Liefert eine Headerzeile zurck, und zwar entweder die erste
  835.  * oder die auf die zuletzt gelieferte folgende. Wenn keine Zeile
  836.  * mehr da ist, dann wird als Ergebnis FALSE zurckgegeben.
  837.  * Ebenso, wenn das Fenster gar kein Anzeigefenster ist
  838.  
  839. TYPE headerInfoType = (headerNone, headerGruppe, headerID, headerKomZu, headerBetreff,
  840.                        headerVon, headerName, headerAn, headerBox, headerRId,
  841.                        headerMId, headerStatus, headerKomAnz, headerEmptyLine);
  842.  *)
  843. VAR ptr : oneWindowPtr;
  844.  
  845.   PROCEDURE ReturnPtr(REF pre : ARRAY OF CHAR; REF str : CatTypes.String255):BOOLEAN;
  846.   (* String in s zusammenstellen *)
  847.   BEGIN
  848.     MagicStrings.Assign(pre, s);
  849.     IF str[0] # 0C THEN
  850.       MagicStrings.Append(str, s);
  851.       RETURN TRUE
  852.     ELSE
  853.       RETURN FALSE
  854.     END;
  855.   END ReturnPtr;
  856.  
  857.   PROCEDURE comment():BOOLEAN;
  858.   BEGIN
  859.     IF ptr^.mess.KommentarAnzahl = 0 THEN
  860.       RETURN FALSE;
  861.     ELSE
  862.       IF ptr^.mess.KommentarAnzahl = 1 THEN
  863.         MagicStrings.Assign('Hierzu gibt es einen Kommentar', s);
  864.       ELSE
  865.         IF ptr^.mess.KommentarAnzahl < 100 THEN
  866.           MagicConvert.CardToStr(ptr^.mess.KommentarAnzahl, 1, s);
  867.         ELSE
  868.           MagicStrings.Assign('xx', s);
  869.         END;
  870.         MagicStrings.Insert('Hierzu gibt es ', s, 0);
  871.         MagicStrings.Append(' Kommentare', s);
  872.       END;
  873.       RETURN TRUE
  874.     END;
  875.   END comment;
  876.  
  877. BEGIN
  878.   IF handlePool.FindEntry(ADR(wdw), FindWinCond, windows, ptr) THEN
  879.     IF which = EditTypes.LFIRST THEN ptr^.lastLine := headerNone END;
  880.     LOOP
  881.       IF ptr^.lastLine = headerEmptyLine THEN
  882.         ptr^.lastLine := headerNone; RETURN FALSE
  883.       ELSE
  884.         INC(ptr^.lastLine);
  885.         CASE ptr^.lastLine OF
  886.           headerGruppe  : GroupSelect.GroupName(ptr^.mess.Gruppe, s); MagicStrings.Insert('Gruppe: ', s, 0); RETURN TRUE;
  887.          |headerID      : v.bool := ReturnPtr('ID:   ', ptr^.mess.MailID^); RETURN TRUE
  888.          |headerKomZu   : IF ReturnPtr('Kommentar zu ', ptr^.mess.KommentierteID) THEN RETURN TRUE END;
  889.          |headerBetreff : v.bool := ReturnPtr('Wg.:  ', ptr^.mess.Betreff^); RETURN TRUE;
  890.          |headerVon     : IF ReturnPtr('Von:  ', ptr^.mess.Absender^) THEN 
  891.                             MagicStrings.Append(' (', s);
  892.                             MagicStrings.Append(ptr^.mess.Datum, s);
  893.                             MagicStrings.Append(')', s);
  894.                             RETURN TRUE
  895.                           END;
  896.          |headerName    : IF ReturnPtr('Name: ', ptr^.mess.name^) THEN RETURN TRUE END;
  897.          |headerAn      : IF ReturnPtr('An:   ', ptr^.mess.Empfaenger^) THEN 
  898.                             IF (ptr^.mess.Gruppe = dataSys.private) & 
  899.                                 ptr^.mess.EigeneNachricht
  900.                             THEN
  901.                               MagicStrings.Append(' (', s);
  902.                               MagicStrings.Append(ptr^.mess.Datum, s);
  903.                               MagicStrings.Append(')', s);
  904.                             END;
  905.                             RETURN TRUE 
  906.                           END;
  907.          |headerBox     : IF ReturnPtr('Box:  ', ptr^.mess.box^) THEN RETURN TRUE END;
  908.          |headerGate    : IF ReturnPtr('Gate: ', ptr^.mess.gate^) THEN RETURN TRUE END;
  909.          |headerMime    : IF ReturnPtr('MIME: ', ptr^.mess.mime^) THEN RETURN TRUE END;
  910.          |headerSender  : IF ReturnPtr('Sender:', ptr^.mess.sender^) THEN RETURN TRUE END;
  911.          |headerReplyTo : IF ReturnPtr('Reply-To:', ptr^.mess.replyTo^) THEN RETURN TRUE END;
  912.          |headerFollowupTo : IF ReturnPtr('Followup-To:', ptr^.mess.followupTo^) THEN RETURN TRUE END;
  913.          |headerRId     : IF ReturnPtr('RId:  ', ptr^.mess.rid^) THEN RETURN TRUE END;
  914.          |headerMId     : IF ReturnPtr('MId:  ', ptr^.mess.mid^) THEN RETURN TRUE END;
  915.          |headerStatus  : IF (ptr^.mess.Gruppe = dataSys.private) & 
  916.                               ptr^.mess.EigeneNachricht
  917.                           THEN
  918.                             GetStatusText (ptr^.mess.Status, s);
  919.                             MagicStrings.Append(' (', s);
  920.                             MagicStrings.Append (ptr^.mess.StatusDatum, s);
  921.                             MagicStrings.Append (' Uhr)', s);
  922.                             MagicStrings.Insert(cStatusDate, s, 0);
  923.                             RETURN TRUE;
  924.                           END; |
  925.          |headerKomAnz  : IF comment() THEN RETURN TRUE END;
  926.          |headerEmptyLine: MagicStrings.Assign(' ', s); RETURN TRUE;
  927.         END;
  928.       END;
  929.     END; (* LOOP *)
  930.   ELSE
  931.     RETURN FALSE
  932.   END;
  933. END grinGetHeaderInfo;
  934.  
  935. (*--- Infozeilen/Fenstertitel einstellen -----------------------*)
  936. (*$H+*)
  937. PROCEDURE ObjcDraw(win, obj : INTEGER; depth : CARDINAL);
  938. (* Wg MultiTOS: bis auf die Prozedur, die der Editor bekommt *)
  939. (* alles sch”n ber die Rechteckliste ausgeben               *)
  940. (* add: Object, das noch dazwischen liegt *)
  941. (* Taucht in dieser Form nur fr ((Tochter)-Tochter)objekte des Grundobjektes *)
  942.  
  943.   VAR r : GrafBase.Rectangle;
  944.       ptr: oneWindowPtr;
  945. BEGIN
  946.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) THEN
  947.     mtUtils.ObjcPos (infoAdr, obj, r.x, r.y);
  948.     DEC (r.x); DEC (r.y);
  949.     r.w := infoAdr^[obj].obWidth+1;
  950.     r.h := infoAdr^[obj].obHeight+1;
  951.     ptr^.inObjcDraw := TRUE;
  952.     WdwManager.RedrawWdw (win, r);
  953.     ptr^.inObjcDraw := FALSE;
  954.   END;
  955. END ObjcDraw;
  956. (*$H=*)
  957.  
  958. PROCEDURE AdjustPosition(x,y,w : INTEGER);
  959. (* Position des Objektes an neue Fensterposition anpassen *)
  960. BEGIN
  961.   infoAdr^[0].obX := x; infoAdr^[0].obY := y;
  962.   infoAdr^[0].obWidth := w;
  963.   (*
  964.   (* Ist fehlerhaft: Bei sehr kleinen Fensterbreiten wird eine negative Breite berechnet! *)
  965.   infoAdr^[MausTauschrsc.wbanzeige].obWidth := infoAdr^[0].obWidth-infoAdr^[MausTauschrsc.wbanzeige].obX;
  966.   *)
  967. END AdjustPosition;
  968.  
  969. (* TYPE dirType = (dPrevMess, dNextMess, dUpMess, dDownMess, dLeftMess, dRightMess, dReturn, dJump, dGroupJump);*)
  970.  
  971. PROCEDURE dirPossible(ptr : oneWindowPtr; dir : dirType; withShift: BOOLEAN):BOOLEAN;
  972. (* Kann man sich in die gewnschte Richtung bewegen? *)
  973. VAR fromWhere : CARDINAL;
  974. BEGIN
  975.   WITH ptr^ DO
  976.     CASE dir OF
  977.       dPrevMess : IF UserBLK.AutoUndo THEN 
  978.                     fromWhere := lastPos
  979.                   ELSE
  980.                     fromWhere := mess.MailNr
  981.                   END;
  982.                   IF withShift THEN (* shift - auf jeden Fall normale Routine verwenden, nicht die Version aus den Listen! *)
  983.                   (* Achtung! Shift hat jetzt eine Doppelbedeutung: *)
  984.                   (* Listen - normales vorw„rts/rckw„rts laufen *)
  985.                   (* normal - toggelt gelesene ignorieren *)
  986.                     RETURN grinNextMess(fromWhere, FALSE, FALSE, 0, NIL) # 0FFFFH;
  987.                   ELSE
  988.                     RETURN nextMsg (fromWhere, FALSE, FALSE, listHdl, NIL) # 0FFFFH
  989.                   END;
  990. (* NIL heižt hier: Nix "Gelesene ignorieren", 2. FALSE : Einstellung auch bei shift nicht invertieren (wrde aber eh' nicht beachtet) *)
  991.     | dNextMess : IF UserBLK.AutoUndo THEN 
  992.                     fromWhere := lastPos
  993.                   ELSE
  994.                     fromWhere := mess.MailNr
  995.                   END;
  996.                   IF withShift THEN
  997.                     RETURN grinNextMess(fromWhere, TRUE, FALSE, 0, NIL) < mess.MailAnz;
  998.                   ELSE
  999.                     RETURN nextMsg (fromWhere, TRUE, FALSE, listHdl, NIL) < mess.MailAnz
  1000.                   END;
  1001.     | dUpMess   : RETURN (mess.up  # dataSys.empty) & (mess.up # dataSys.notSaved) 
  1002.     | dDownMess : RETURN mess.down  # dataSys.empty 
  1003.     | dLeftMess : RETURN (mess.left  # dataSys.empty)
  1004.     | dRightMess: RETURN (mess.right  # dataSys.empty)
  1005.     | dReturn   : RETURN ptr^.lastPos # mess.MailNr
  1006.     ELSE
  1007.       RETURN TRUE;
  1008.     END;
  1009.   END;
  1010. END dirPossible;
  1011.  
  1012. PROCEDURE whiteNr(dir : dirType):INTEGER;
  1013. (* liefert Resourceindex des weižen Pfeils *)
  1014. BEGIN
  1015.   CASE dir OF
  1016.     dPrevMess : RETURN MausTauschrsc.wprevmess
  1017.   | dNextMess : RETURN MausTauschrsc.wnextmess
  1018.   | dUpMess   : RETURN MausTauschrsc.wupmess
  1019.   | dDownMess : RETURN MausTauschrsc.wdownmess
  1020.   | dLeftMess : RETURN MausTauschrsc.wleftmess
  1021.   | dRightMess: RETURN MausTauschrsc.wrightmess
  1022.   | dReturn   : RETURN MausTauschrsc.return
  1023.   ELSE
  1024.   END;
  1025. END whiteNr;
  1026.  
  1027. PROCEDURE blackNr(dir : dirType):INTEGER;
  1028. (* liefert Resourceindex des schwarzen Pfeils *)
  1029. BEGIN
  1030.   CASE dir OF
  1031.     dPrevMess : RETURN MausTauschrsc.wprevmess
  1032.   | dNextMess : RETURN MausTauschrsc.wnextmess
  1033.   | dUpMess   : RETURN MausTauschrsc.whupmess
  1034.   | dDownMess : RETURN MausTauschrsc.whdownmess
  1035.   | dLeftMess : RETURN MausTauschrsc.whleftmess
  1036.   | dRightMess: RETURN MausTauschrsc.whrightmess
  1037.   | dReturn   : RETURN MausTauschrsc.hreturn
  1038.   ELSE
  1039.   END;
  1040. END blackNr;
  1041.  
  1042. PROCEDURE BlackArrow(win : INTEGER; dir : dirType);
  1043. (* Richtungspfeil schwarz einf„rben *)
  1044. VAR clip : GrafBase.Rectangle;
  1045. BEGIN
  1046.   WdwManager.GetWdwWork (win, clip);
  1047.   AdjustPosition(clip.x, clip.y, clip.w);
  1048.   CASE dir OF
  1049.     dPrevMess,
  1050.     dNextMess : mtUtils.InclState (infoAdr, blackNr(dir), MagicAES.SELECTED);
  1051.   ELSE
  1052.     mtUtils.ExclFlag (infoAdr, blackNr(dir), MagicAES.HIDETREE);
  1053.   END;
  1054.   ObjcDraw(win, whiteNr(dir), 2);
  1055. END BlackArrow;
  1056.  
  1057. PROCEDURE WhiteArrow(win: INTEGER; dir : dirType; redraw: BOOLEAN);
  1058. (* Flag wieder zurcknehmen, gezeichnet werden muž noch *)
  1059. BEGIN
  1060.   CASE dir OF
  1061.     dPrevMess,
  1062.     dNextMess : mtUtils.ExclState (infoAdr, blackNr(dir), MagicAES.SELECTED);
  1063.   ELSE
  1064.     mtUtils.InclFlag (infoAdr, blackNr(dir), MagicAES.HIDETREE);
  1065.   END;
  1066.   IF redraw THEN ObjcDraw(win, whiteNr(dir), 2); END;
  1067. END WhiteArrow;
  1068.  
  1069. PROCEDURE ComposeInfoline(ptr : oneWindowPtr);
  1070.  VAR tmp : ARRAY [0..10] OF CHAR;
  1071. BEGIN
  1072.   WITH ptr^ DO
  1073.     MagicStrings.Assign(rawInfoline, info);
  1074.     VDIStandards.StatusCheck(mess.StatusBits);
  1075.     IF mess.left  # dataSys.empty THEN info[0] := 04C END;
  1076.     IF mess.up    # dataSys.empty THEN info[1] := 01C END;
  1077.     IF mess.down  # dataSys.empty THEN info[2] := 02C END;
  1078.     IF mess.right # dataSys.empty THEN info[3] := 03C END;
  1079.     IF 0 IN mess.StatusBits THEN info[5]  := 'L' END;
  1080.     IF 1 IN mess.StatusBits THEN info[6]  := 'F' END;
  1081.     IF 2 IN mess.StatusBits THEN info[7]  := 'I' END;
  1082.     IF 3 IN mess.StatusBits THEN info[8]  := 'T' END;
  1083.     IF 4 IN mess.StatusBits THEN info[9]  := 'D' END;
  1084.     IF 5 IN mess.StatusBits THEN info[10] := 'K' END;
  1085.     IF 6 IN mess.StatusBits THEN info[11] := 'B' END;
  1086.     IF 7 IN mess.StatusBits THEN info[12] := '1' END;
  1087.     IF 8 IN mess.StatusBits THEN info[13] := '2' END;
  1088.     IF 9 IN mess.StatusBits THEN info[14] := 'V' END;
  1089.     IF mess.EigeneNachricht & (mess.Gruppe = dataSys.private) THEN
  1090.       MagicStrings.Append(openBracket, info);
  1091.       MagicStrings.Append(mess.Datum, info);
  1092.       MagicStrings.Append(closeBracket, info);
  1093.       MagicStrings.Append(spaceString, info);
  1094.     END;
  1095.     (*
  1096.     IF mess.MailAnz = 1 THEN
  1097.       infoAdr^[MausTauschrsc.wanzeige].obWidth := infoAdr^[MausTauschrsc.wbanzeige].obWidth;
  1098.     ELSE
  1099.       infoAdr^[MausTauschrsc.wanzeige].obWidth := BinOps.HigherInt(1,
  1100.         SHORT((LONG(CARDINAL(infoAdr^[MausTauschrsc.wbanzeige].obWidth)) * LONG(mess.MailNr)) DIV LONG(mess.MailAnz-1)));
  1101.     END;
  1102.     *)
  1103.     MagicStrings.Append(mess.Betreff^, info);
  1104.     (* Statusinformationen reinkopieren, Achtung, wenn sie nicht *)
  1105.     (* zusammengestellt wurde!                                   *)
  1106.     MagicStrings.Copy(info, 5, 10, tmp);
  1107.     mtUtils.SetObjcString (infoAdr, MausTauschrsc.wstati, tmp);
  1108.     mtUtils.SetState (infoAdr, MausTauschrsc.winfo, MagicAES.SELECTED, ptr^.viewHeader = vhFull);
  1109.   END;
  1110. END ComposeInfoline;
  1111.  
  1112. PROCEDURE SetNShowNewStates(ptr : oneWindowPtr);
  1113. VAR clip : GrafBase.Rectangle;
  1114. BEGIN
  1115.   ComposeInfoline(ptr);
  1116.   WdwManager.GetWdwWork (ptr^.win, clip);
  1117.   AdjustPosition(clip.x, clip.y, clip.w);
  1118.   ObjcDraw(ptr^.win, MausTauschrsc.wstati, 1);
  1119.   WITH ptr^ DO
  1120.     msgList.listChangeFlags (listHdl, win, mess.MailNr, mess.StatusBits);
  1121.   END;
  1122. END SetNShowNewStates;
  1123.  
  1124. PROCEDURE setState(ptr : oneWindowPtr);
  1125. (* Status bei pers”nlichen Msgs setzen *)
  1126. (* Achtung, kopiert direkt in die Resource, deswegen muž *)
  1127. (* dort gengend Platz vorhanden sein!                   *)
  1128. VAR status : ARRAY[0..18] OF CHAR;
  1129.  (* Wenn gr”žer, dann auch in der Resource anpassen! *)
  1130. BEGIN
  1131.   WITH ptr^ DO
  1132.     IF mess.Gruppe = dataSys.private
  1133.     THEN
  1134.       GetStatusText (mess.Status, status);
  1135.       mtUtils.SetObjcString (infoAdr, MausTauschrsc.wmperstatus, status);
  1136.       mtUtils.ExclFlag (infoAdr, MausTauschrsc.wmperstatus, MagicAES.HIDETREE);
  1137.     ELSE
  1138.       mtUtils.InclFlag (infoAdr, MausTauschrsc.wmperstatus, MagicAES.HIDETREE);
  1139.     END;
  1140.   END;
  1141. END setState;
  1142.  
  1143. TYPE changeProc = PROCEDURE((* oldBits *) BITSET):BITSET; (* newBits *)
  1144.  
  1145. (* Da sie als Prozedurparameter ben”tigt wird, hier als globale Prozedur mit Variablen *)
  1146. VAR CLEARBITS, SETBITS : BITSET;
  1147. PROCEDURE newBits(old : BITSET):BITSET;
  1148. BEGIN
  1149.   RETURN (old-CLEARBITS)+SETBITS;
  1150. END newBits;
  1151.  
  1152. (*$H+*)
  1153. PROCEDURE iInternalChange(handle : handlePool.oneHandlePtr; gruppe, MailNr : CARDINAL; actualBits : BITSET; newBits : changeProc);
  1154. (* alle Fenster werden durchsucht, ob sie diese Msg *)
  1155. (* aus dieser Gruppe darstellen und dort der Status gesetzt *)
  1156.  
  1157.   (*$Z-*)
  1158.   PROCEDURE scanWinCond(e, i : ADDRESS):BOOLEAN;
  1159.   (* Abbruchprozedur, wie in <Lists> gefordert *)
  1160.   VAR p : oneWindowPtr; old : BITSET;
  1161.   BEGIN
  1162.     IF e # NIL THEN
  1163.       p := e;
  1164.       IF (p^.mess.Gruppe = gruppe) & (p^.mess.MailNr = MailNr) THEN
  1165.         WITH p^ DO
  1166.           old := mess.StatusBits;
  1167.           mess.StatusBits := newBits(mess.StatusBits);
  1168.           IF (dataSys.bGelesen IN old) & ~(dataSys.bGelesen IN mess.StatusBits) THEN 
  1169.           (* Der andere Fall ist unkritisch.. :-) *)
  1170.             p^.readchange := TRUE
  1171.           END;
  1172.         END;
  1173.         SetNShowNewStates(p);
  1174.       END;
  1175.     END;
  1176.     RETURN FALSE
  1177.   END scanWinCond;
  1178.   (*$Z=*)
  1179.  
  1180. BEGIN
  1181.   data.SetBits(handle^.Zugriff, MailNr, newBits(actualBits));
  1182.   (* Jetzt alle Eintr„ge durchsuchen und die Stati neu setzen *)
  1183.   Lists.ResetList(windows);
  1184.   Lists.ScanEntries(windows, Lists.forward, scanWinCond, NIL, v.bool);
  1185. END iInternalChange;
  1186.  
  1187. PROCEDURE InternalChange(ptr : oneWindowPtr; newBits : changeProc);
  1188. BEGIN
  1189.   WITH ptr^ DO
  1190.     iInternalChange(handle, mess.Gruppe, mess.MailNr, mess.StatusBits, newBits);
  1191.   END;
  1192. END InternalChange;
  1193. (*$H=*)
  1194.  
  1195. PROCEDURE iChangeState(handle : handlePool.oneHandlePtr; gruppe, MailNr : CARDINAL; actualBits : BITSET; oldState, newState : CHAR);
  1196. (* Alle Fenster werden durchsucht, ob sie dieselbe Msg aus dieser Gruppe darstellen  *)
  1197. (* und dort auch der Status gesetzt            *)
  1198.  
  1199.   (*$A+,Z-*)
  1200.   PROCEDURE scanWinCond(e, i : ADDRESS):BOOLEAN;
  1201.   (* Abbruchprozedur, wie in <Lists> gefordert *)
  1202.   VAR p : oneWindowPtr;
  1203.       clip : GrafBase.Rectangle;
  1204.   BEGIN
  1205.     IF e # NIL THEN
  1206.       p := e;
  1207.       IF (p^.mess.Gruppe = gruppe) & (p^.mess.MailNr = MailNr) THEN
  1208.         WITH p^ DO
  1209.           WdwManager.GetWdwWork (win, clip);
  1210.           AdjustPosition(clip.x, clip.y, clip.w);
  1211.           mess.Status := newState;
  1212.           setState(p);
  1213.           ObjcDraw(win, MausTauschrsc.wmperstatus, 1);
  1214.         END;
  1215.       END;
  1216.     END;
  1217.     RETURN FALSE
  1218.   END scanWinCond;
  1219.   (*$A=,Z=*)
  1220.  
  1221. (* Status in Datenbank und interner Struktur „ndern sowie zeichnen *)
  1222. BEGIN
  1223.   data.ChangeState(handle^.Zugriff, MailNr, newState);
  1224.   Lists.ResetList(windows);
  1225.   Lists.ScanEntries(windows, Lists.forward, scanWinCond, NIL, v.bool);
  1226.   IF newState = 'Z' THEN
  1227.     CLEARBITS := {};
  1228.     SETBITS   := {dataSys.bAntworten};
  1229.     iInternalChange(handle, gruppe, MailNr, actualBits, newBits);
  1230.   ELSIF (newState = 'B') OR (newState = 'G') THEN
  1231.     CLEARBITS := {dataSys.bAntworten};
  1232.     SETBITS   := {};
  1233.     iInternalChange(handle, gruppe, MailNr, actualBits, newBits);
  1234.   END;
  1235. END iChangeState;
  1236.  
  1237. PROCEDURE changeState(ptr : oneWindowPtr; newState : CHAR);
  1238. (* ptr : Das Fenster, das die Žnderung hervorgerufen hat *)
  1239. (* Anschliežend werden alle anderen Fenster durchsucht, ob sie dieselbe Msg *)
  1240. (* aus dieser Gruppe darstellen und dort auch der Status gesetzt            *)
  1241. (* Status in Datenbank und interner Struktur „ndern sowie zeichnen *)
  1242. BEGIN
  1243.   WITH ptr^ DO
  1244.     iChangeState(handle, mess.Gruppe, mess.MailNr, mess.StatusBits, mess.Status, newState);
  1245.   END;
  1246. END changeState;
  1247.  
  1248. PROCEDURE grinResetState(REF id : ARRAY OF CHAR);
  1249. (* Den Status einer pers”nlichen Msg zurcksetzen, wenn eine noch nicht abgeschickte *)
  1250. (* Antwort dazu gel”scht wird. *)
  1251. VAR handle : handlePool.oneHandlePtr;
  1252.     which  : CARDINAL;
  1253.     own    : BOOLEAN;
  1254.     state  : CHAR;
  1255.     bits   : BITSET;
  1256. BEGIN
  1257.   IF handlePool.GetOneDatahandle(dataSys.private, handle) THEN
  1258.     which := data.NumberOfID(handle^.Zugriff, id);
  1259.     IF data.error = data.noError THEN
  1260.       IF ~data.HasAnswer(handle^.Zugriff, which, bits) THEN
  1261.         data.ReadPersState(handle^.Zugriff, which, state, own, v.bset);
  1262.         IF state = 'B' THEN iChangeState(handle, dataSys.private, which, bits, 'B', 'Z'); END;
  1263.       END;
  1264.     END;
  1265.     handlePool.FreeOneDataHandle(handle);
  1266.   END;
  1267. END grinResetState;
  1268.  
  1269. PROCEDURE MakeInfoline(ptr : oneWindowPtr);
  1270. (* Infozeile und die Box bereitstellen *)
  1271. VAR scrap : ARRAY[0..4] OF CHAR;
  1272.     num   : ARRAY[0..12] OF CHAR;
  1273.     dirZaehl : dirType;
  1274. BEGIN
  1275.   WITH ptr^ DO
  1276.     IF inObjcDraw THEN RETURN END;
  1277.     ComposeInfoline(ptr);
  1278.     FOR dirZaehl := dPrevMess TO dReturn DO
  1279.       WhiteArrow(win, dirZaehl, FALSE);
  1280.       IF dirPossible(ptr, dirZaehl, TRUE) THEN
  1281.         mtUtils.ExclState (infoAdr, whiteNr(dirZaehl), MagicAES.DISABLED);
  1282.       ELSE
  1283.         mtUtils.InclState (infoAdr, whiteNr(dirZaehl), MagicAES.DISABLED);
  1284.       END;
  1285.     END;
  1286.     mtUtils.SetObjcString (infoAdr, MausTauschrsc.wwegen, ptr^.mess.Betreff^);
  1287.     IF (ptr^.mess.EigeneNachricht) & (mess.Gruppe = dataSys.private)
  1288.     THEN
  1289.       mtUtils.SetObjcString (infoAdr, MausTauschrsc.wvon, ptr^.mess.Empfaenger^);
  1290.     ELSE
  1291.       IF ptr^.mess.name^[0] = 0C THEN
  1292.         mtUtils.SetObjcString (infoAdr, MausTauschrsc.wvon, ptr^.mess.Absender^);
  1293.       ELSE
  1294.         mtUtils.SetObjcString (infoAdr, MausTauschrsc.wvon, ptr^.mess.name^);
  1295.       END;
  1296.     END;
  1297.     mtUtils.SetObjcStringAdr (infoAdr, MausTauschrsc.wdatum, ADR(ptr^.mess.Datum));
  1298.     IF mess.EigeneNachricht & (mess.Gruppe = dataSys.private)
  1299.     THEN
  1300.       mtUtils.SetObjcString (infoAdr, MausTauschrsc.wprevon, 'An:');
  1301.     ELSE
  1302.       mtUtils.SetObjcString (infoAdr, MausTauschrsc.wprevon, 'Von:');
  1303.     END;
  1304.  
  1305.     IF mess.KommentarAnzahl < 100 THEN
  1306.       MagicConvert.CardToStr(mess.KommentarAnzahl, 2, scrap);
  1307.     ELSE
  1308.       scrap := 'xx';
  1309.     END;
  1310.     mtUtils.SetObjcString (infoAdr, MausTauschrsc.wkomanz, scrap);
  1311.  
  1312.     IF mess.up = dataSys.notSaved THEN
  1313.       mtUtils.ExclFlag (infoAdr, MausTauschrsc.deletedup, MagicAES.HIDETREE);
  1314.     ELSE
  1315.       mtUtils.InclFlag (infoAdr, MausTauschrsc.deletedup, MagicAES.HIDETREE);
  1316.     END;
  1317.  
  1318.     IF dataSys.bOwnMessage IN mess.StatusBits THEN
  1319.       mtUtils.SetObjcString(infoAdr, MausTauschrsc.showownmessage, 'E');
  1320.       mtUtils.ExclFlag (infoAdr, MausTauschrsc.showownmessage, MagicAES.HIDETREE);
  1321.     ELSIF (dataSys.bComToOwnMessage IN mess.StatusBits) OR
  1322.           (dataSys.bOldComToOwnMessage IN mess.StatusBits) THEN
  1323.       mtUtils.SetObjcString(infoAdr, MausTauschrsc.showownmessage, 'K');
  1324.       mtUtils.ExclFlag (infoAdr, MausTauschrsc.showownmessage, MagicAES.HIDETREE);
  1325.     ELSE
  1326.       mtUtils.InclFlag (infoAdr, MausTauschrsc.showownmessage, MagicAES.HIDETREE);
  1327.     END;
  1328.  
  1329.     IF mess.distribution # data.dNone THEN
  1330.       mtUtils.SetObjcString(infoAdr, MausTauschrsc.stdistribution, CHR(ORD(mess.distribution)+ORD('K')));
  1331.       mtUtils.ExclFlag (infoAdr, MausTauschrsc.stdistribution, MagicAES.HIDETREE);
  1332.     (*
  1333.     ELSIF mess.distribution = data.dMausNet THEN
  1334.       mtUtils.SetObjcString(infoAdr, MausTauschrsc.stdistribution, 'M');
  1335.       mtUtils.ExclFlag (infoAdr, MausTauschrsc.stdistribution, MagicAES.HIDETREE);
  1336.     ELSIF mess.distribution = data.dNet THEN
  1337.       mtUtils.SetObjcString(infoAdr, MausTauschrsc.stdistribution, 'N');
  1338.       mtUtils.ExclFlag (infoAdr, MausTauschrsc.stdistribution, MagicAES.HIDETREE);
  1339.     *)
  1340.     ELSE (* Keine Distribution *)
  1341.       mtUtils.InclFlag (infoAdr, MausTauschrsc.stdistribution, MagicAES.HIDETREE);
  1342.     END;
  1343.  
  1344.     MagicConvert.CardToStr(mess.MailNr+1, 0, num);
  1345.     MagicStrings.Append('/', num);
  1346.     MagicConvert.CardToStr(mess.MailAnz, 0, scrap);
  1347.     MagicStrings.Append(scrap, num);
  1348.     mtUtils.SetObjcString (infoAdr, MausTauschrsc.wpos, num);
  1349.   END; (* WITH ptr^ *)
  1350.   setState(ptr);
  1351. END MakeInfoline;
  1352.  
  1353. PROCEDURE MakeTitle(ptr : oneWindowPtr);
  1354. BEGIN
  1355.   WITH ptr^ DO
  1356.     GroupSelect.GroupName(handle^.group, title);
  1357.     ConfVars.GetConfDefBool (cSetAppName, v.bool, TRUE);
  1358.     IF CatGlobal.multiTask & v.bool
  1359.     THEN
  1360.       MagicStrings.Insert ('[CAT] ', title, 0);
  1361.     END;
  1362.     MagicStrings.Insert (' ', title, 0);
  1363.     MagicStrings.Append (' ', title);
  1364.   END;
  1365. END MakeTitle;
  1366.  
  1367. (*--- Umschalten einer Message ---------------------*)
  1368.  
  1369. PROCEDURE setReadFlag(ptr : oneWindowPtr);
  1370.   PROCEDURE new(old : BITSET):BITSET; BEGIN RETURN ptr^.mess.StatusBits; END new;
  1371. BEGIN
  1372.   IF ~(dataSys.bGelesen IN ptr^.mess.StatusBits) & ~ptr^.readchange THEN
  1373.     INCL(ptr^.mess.StatusBits, dataSys.bGelesen);
  1374.     data.SetBits(ptr^.handle^.Zugriff, ptr^.mess.MailNr, ptr^.mess.StatusBits);
  1375.     InternalChange(ptr, new);
  1376.   END;
  1377. END setReadFlag;
  1378.  
  1379. PROCEDURE StoreUndoPos(ptr : oneWindowPtr);
  1380. (* Speichert die letzten Positionen fr <undo> *)
  1381. BEGIN
  1382.   WITH ptr^ DO
  1383.     undoPos    := mess.MailNr;
  1384.     undoGroup  := mess.Gruppe;
  1385.   END;
  1386. END StoreUndoPos;
  1387.  
  1388. PROCEDURE StoreLastPos(ptr : oneWindowPtr; dir : dirType);
  1389. (* Speichert die letzte Position fr die Kommentarverkettung *)
  1390. BEGIN
  1391.   WITH ptr^ DO
  1392.     IF (dir = dPrevMess) OR (dir = dNextMess) OR
  1393.        (dir = dJump)     OR (dir = dGroupJump)
  1394.     THEN
  1395.       undoTreeRoot := lastPos;
  1396.       lastPos := mess.MailNr;
  1397.     END;
  1398.   END;
  1399. END StoreLastPos;
  1400.  
  1401. PROCEDURE SwitchTo(ptr : oneWindowPtr; nr : CARDINAL; dir : dirType; isUndo : BOOLEAN);
  1402. (* Wechselt zu der angegebenen Nachricht *)
  1403. VAR last : CARDINAL; 
  1404.     inEffMode : BOOLEAN;
  1405.     num  : INTEGER;
  1406.     iFont,
  1407.     iFontSize : INTEGER;
  1408.     varName   : CatTypes.String255;
  1409. BEGIN
  1410.   IF (nr # dataSys.empty) & (nr # dataSys.notSaved) & 
  1411.      ((nr # ptr^.mess.MailNr) OR (dir=dNextMess) OR (dir = dJump) OR (dir = dNone)) 
  1412.   THEN
  1413.     IF ptr^.treeMode THEN
  1414.       DEALLOCATE(ptr^.stack, 0);
  1415.       ptr^.treeMode := FALSE;
  1416.     END;
  1417.     IF (dir # dNone) & (dir # dJump) & (dir # dGroupJump) THEN
  1418.       BlackArrow(ptr^.win, dir);
  1419.     END;
  1420.     IF (dir # dGroupJump) & (dir # dNone) THEN 
  1421.       (* Dann ist dieser Handle schon freigegeben und das Flag auch schon gesetzt *)
  1422.       setReadFlag(ptr);
  1423.       StoreUndoPos(ptr);
  1424.       last := ptr^.mess.MailNr;
  1425.     ELSE
  1426.       last := dataSys.empty;
  1427.     END;
  1428.     ptr^.readchange := FALSE; (* NACH setReadFlag, jetzt neue Msg, User hat noch nix getan *)
  1429.     DEALLOCATE(ptr^.mess.InfoStrings, 0);
  1430.     IF GetOneMessage(ptr, nr) THEN
  1431.       IF isUndo THEN 
  1432.         v.card := ptr^.lastPos;
  1433.         ptr^.lastPos := ptr^.undoTreeRoot;
  1434.         ptr^.undoTreeRoot := v.card;
  1435.       ELSE
  1436.         StoreLastPos(ptr, dir);
  1437.       END; 
  1438.       data.SetLastReadMsg(ptr^.handle^.group, ptr^.mess.MailNr);    
  1439.  
  1440.       WITH ptr^ DO (* ... und das ganze an den Editor bergeben *)
  1441.         inEffMode := CatEdit.GetMode (win, CatEdit.effMode);
  1442.         CatEdit.ShowNewBuffer (win, title, info, viewBuff (* mess.Text *) , 
  1443.                                viewLen (* LONG(mess.textLen)*) , viewAllocated (* ~refSuppressed *), 
  1444.                                isEnriched);
  1445.                           (* dorthin kommt das Fensterhandle im Erfolgsfall *)
  1446.           (* jetzt im Editor, doppelt wg. Struktur *)
  1447.         Protokoll.SendNewMsgInWdw();
  1448.         IF inEffMode # CatEdit.GetMode (win, CatEdit.effMode)
  1449.         THEN
  1450.           (* Font umschalten *)
  1451.           IF CatEdit.GetMode (win, CatEdit.effMode)
  1452.           OR ~ConfVars.GetConfigInt (cMsgAltFont, iFont)
  1453.           THEN
  1454.             (* Mit Effekten, normaler Font *)
  1455.             num := BinOps.HigherInt (number-1, 0);
  1456.             Strings.Concat (cMsgFont, StrConv.IntToStr (num, 0), varName,   v.bool);
  1457.             ConfVars.GetConfDefInt (varName, iFont, 1);
  1458.             Strings.Concat (cMsgSize, StrConv.IntToStr (num, 0), varName, v.bool);
  1459.             ConfVars.GetConfDefInt (varName, iFontSize, 10);
  1460.             CatEdit.SelectEditFont (win, iFont, iFontSize);
  1461.           ELSE
  1462.             (* Ohne Effekte, Tabellenfont *)
  1463.             IF ConfVars.GetConfigInt (cMsgAltFont, iFont)
  1464.             THEN
  1465.               ConfVars.GetConfDefInt (cMsgAltSize, iFontSize, 10);
  1466.               CatEdit.SelectEditFont (win, iFont, iFontSize);
  1467.             END;
  1468.           END;
  1469.         END;
  1470.         IF (dataSys.bComToOwnMessage IN mess.StatusBits)  OR
  1471.            (dataSys.bOldComToOwnMessage IN mess.StatusBits) 
  1472.         (* OR (dataSys.bOwnMessage      IN mess.StatusBits) 
  1473.         *)
  1474.         THEN
  1475.           IF dir # dNone THEN CatGlobal.Bing (0) END;
  1476.         END;
  1477.         (* Das freigeben fehlte noch! *)
  1478.         IF ptr^.refSuppressed & (ptr^.originalText # NIL)
  1479.         THEN
  1480.           DEALLOCATE(ptr^.originalText, 0);
  1481.           ptr^.refSuppressed := FALSE;
  1482.         ELSE
  1483.           IF viewAllocated
  1484.           THEN 
  1485.             DEALLOCATE(ptr^.mess.Text, 0); 
  1486.           END;
  1487.         END;
  1488.       END;
  1489.     ELSE
  1490.       (* Hier versuchen, die alte wieder zu ”ffnen, falls das nicht *)
  1491.       (* m”glich ist, meckern und schliežen                         *)
  1492.       v.int := mtAlerts.Alert(1, MTE.msgError);
  1493.       IF (last # dataSys.empty) & GetOneMessage(ptr, last) THEN
  1494.         IF ptr^.refSuppressed & (ptr^.originalText # NIL)
  1495.         THEN
  1496.           DEALLOCATE(ptr^.originalText, 0); 
  1497.           ptr^.refSuppressed := FALSE;
  1498.         ELSE
  1499.           DEALLOCATE(ptr^.mess.Text, 0); 
  1500.         END;
  1501.         IF ptr^.viewAllocated
  1502.         THEN
  1503.           DEALLOCATE(ptr^.viewBuff, 0); 
  1504.         END;
  1505.         (* Der Editor bekommt von unserer kleinen "Transaktion" nichts mit.. :-) *)
  1506.       ELSE 
  1507.         (* entweder war dies ein Gruppenwechsel und der Handle ist schon weg *)
  1508.         (* oder die alte Msg l„žt sich nicht lesen (Speicher, Platte..)      *)
  1509.         MTE.info (MTE.noOldMsg);
  1510.         grinClose(ptr^.win);
  1511.       END;
  1512.       (* Hier noch die Buttons wieder deselektieren *)
  1513.       IF (dir # dJump) & (dir # dGroupJump) & (dir # dNone) THEN
  1514.         WhiteArrow(ptr^.win, dir, TRUE);
  1515.       END;
  1516.     END;
  1517.   END;
  1518. END SwitchTo;
  1519.  
  1520. PROCEDURE grinSwitchTo (win : INTEGER; which : CARDINAL;
  1521.                         nextMess : grinNextMessProc; listHandle: LONGCARD;
  1522.                         doNotTop: BOOLEAN): BOOLEAN;     (* exported *)
  1523. (* Schaltet in der aktuellen Gruppe zu der Nachricht which um *)
  1524. (* Exportiert fr die Msgliste *)
  1525. VAR ptr : oneWindowPtr;
  1526. BEGIN
  1527.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) 
  1528.   THEN
  1529.     msgList.listUnlockWdw (ptr^.listHdl);
  1530.     ptr^.listHdl := listHandle;
  1531.     ptr^.nextMsg := nextMess;
  1532.     SwitchTo (ptr, which, dJump, FALSE);
  1533.     IF ~doNotTop THEN WdwManager.TopWindow (win); END;
  1534.     RETURN TRUE;
  1535.   END;
  1536.   RETURN FALSE;
  1537. END grinSwitchTo;
  1538.  
  1539. PROCEDURE grinSetListWdw (win : INTEGER; nextMess : grinNextMessProc; 
  1540.                           listHandle: LONGCARD): BOOLEAN;     (* exported *)
  1541. (* Exportiert fr die Msgliste *)
  1542. VAR ptr : oneWindowPtr;
  1543. BEGIN
  1544.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) 
  1545.   THEN
  1546.     ptr^.listHdl := listHandle;
  1547.     ptr^.nextMsg := nextMess;
  1548.     RETURN TRUE;
  1549.   END;
  1550.   RETURN FALSE;
  1551. END grinSetListWdw;
  1552.  
  1553. PROCEDURE SwitchToNewGroup(group, nr : CARDINAL; ptr : oneWindowPtr);
  1554. (* Hier k”nnen wir uns notfalls immer noch entscheiden, ein neues Fenster *)
  1555. (* aufzumachen. Evtl. auch optional, natrlich!                           *)
  1556. VAR newHandle : handlePool.oneHandlePtr;
  1557. BEGIN
  1558.   setReadFlag(ptr);
  1559.   IF handlePool.GetOneDatahandle(group, newHandle) THEN
  1560.     StoreUndoPos(ptr);
  1561.     handlePool.FreeOneDataHandle(ptr^.handle); (* Alten freigeben *)
  1562.     ptr^.handle := newHandle;
  1563.     MakeTitle(ptr);
  1564.     ptr^.mess.MailNr := 0FFFFH; (* Nunja, wird oben getestet *)
  1565.     SwitchTo(ptr, nr, dGroupJump, FALSE);
  1566.   ELSE
  1567. (* Das Fenster kann offen bleiben, nichts wurde ge„ndert!
  1568.     ptr^.handle := NIL;
  1569.     grinClose(ptr^.win);
  1570. *)
  1571.     MTE.info (MTE.msgError);
  1572.   END;
  1573. END SwitchToNewGroup;
  1574.  
  1575. PROCEDURE grinSwitchToMess (win : INTEGER; group : CARDINAL;
  1576.                             whichNumber: getNumberProc):BOOLEAN;
  1577. (* Neue Msg in ein Fenster setzen; Fr die Wiedervorlage *)
  1578. VAR ptr : oneWindowPtr;
  1579.     mess: CARDINAL;
  1580.     newHandle : handlePool.oneHandlePtr;
  1581. BEGIN
  1582.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) THEN
  1583.     msgList.listUnlockWdw (ptr^.listHdl);
  1584.     ptr^.listHdl := 0;
  1585.     IF ptr^.mess.Gruppe = group THEN
  1586.       mess := whichNumber(ptr^.handle^.Zugriff);
  1587.       SwitchTo (ptr, mess, dJump, FALSE);
  1588.     ELSE
  1589.       IF handlePool.GetOneDatahandle(group, newHandle) THEN
  1590.         mess := whichNumber(newHandle^.Zugriff);
  1591.         handlePool.FreeOneDataHandle(newHandle); (* Alten freigeben *)
  1592.         SwitchToNewGroup(group, mess, ptr);
  1593.       END;
  1594.     END;
  1595.     RETURN TRUE;
  1596.   ELSE
  1597.     RETURN FALSE;
  1598.   END;
  1599. END grinSwitchToMess;
  1600.  
  1601. PROCEDURE grinNextNotWorked (topWin : INTEGER; withShift : BOOLEAN);
  1602. (* Springt zur n„chsten nicht bearbeiteten Msg bei den pers”nlichen Msgs *)
  1603. VAR ptr : oneWindowPtr;
  1604.     flagsok : BOOLEAN;
  1605.  
  1606.   PROCEDURE flagsOk(which : CARDINAL):BOOLEAN;
  1607.   VAR state : CHAR; own : BOOLEAN; bits : BITSET;
  1608.   BEGIN
  1609.     data.ReadPersState(ptr^.handle^.Zugriff, which, state, own, bits);
  1610.     flagsok := ~own & ((state = 'N') OR (state = 'Z')) OR (bits - (BITSET(0FFFFH)-{dataSys.bAntworten, dataSys.bKommentieren}) # {});
  1611.     RETURN flagsok;
  1612.   END flagsOk;
  1613.  
  1614.   PROCEDURE next(which : CARDINAL):CARDINAL;
  1615.   BEGIN
  1616.     (*$R-*)
  1617.     IF withShift THEN
  1618.       RETURN which - 1
  1619.     ELSE
  1620.       RETURN which + 1
  1621.     END;
  1622.     (*$R=*)
  1623.   END next;
  1624.  
  1625.   (*$R- wegen Compiler-Bug*)
  1626.  
  1627. VAR which   : CARDINAL; dreh : CARDINAL;
  1628. BEGIN
  1629.   IF handlePool.FindEntry(ADR(topWin), FindWinCond, windows, ptr) THEN
  1630.     flagsok := FALSE;
  1631.     which := ptr^.mess.MailNr;
  1632.     IF ((which = 0) & withShift) OR ((which >= ptr^.mess.MailAnz) & ~withShift) THEN
  1633.     ELSE
  1634.       dreh := 0;
  1635.       CatGlobal.busyMouse();
  1636.       REPEAT
  1637.         which := next(which);
  1638.         IF ptr^.handle^.group = dataSys.private THEN
  1639.           INC(dreh);
  1640.           IF dreh = 10 THEN 
  1641.             dreh := 0; CatGlobal.busyMouse(); 
  1642.             IF stopSearch() THEN mtAppl.MouseArrow(); RETURN END;
  1643.           END;
  1644.         END;
  1645.       UNTIL flagsOk(which) OR (which >= ptr^.mess.MailAnz) OR (which = 0) ;
  1646.       mtAppl.MouseArrow();
  1647.     END;
  1648.     IF flagsok THEN
  1649.       SwitchTo(ptr, which, dJump, FALSE);
  1650.     ELSE
  1651.       CatGlobal.Bing (0);
  1652.     END;
  1653.   END;
  1654. END grinNextNotWorked;
  1655.  
  1656. (* TYPE dirType = (dPrevMess, dNextMess, dUpMess, dDownMess, dLeftMess, dRightMess); *)
  1657. PROCEDURE grinNextMess (which : CARDINAL; nextJN, withShift : BOOLEAN; listHandle: LONGCARD; winp: ADDRESS): CARDINAL;
  1658. (* Default-Prozedur fr n„chste/letzte Message *)
  1659. (* winp = NIL -> Gelesene ignorieren nicht beachten *)
  1660. VAR ptr : oneWindowPtr;
  1661.     ignoreReadMsgs : BOOLEAN;
  1662.  
  1663.   PROCEDURE flagsNotOk(which : CARDINAL):BOOLEAN;
  1664.   VAR flags : BITSET;
  1665.   BEGIN
  1666.     data.ReadState(ptr^.handle^.Zugriff, which, flags);
  1667.     RETURN ((dataSys.bGelesen IN flags) & (ignoreReadMsgs))
  1668.         OR ((dataSys.bFiltered IN flags) & (UserBLK.ignoreFiltered))
  1669.   END flagsNotOk;
  1670.  
  1671.   PROCEDURE next(which : CARDINAL):CARDINAL;
  1672.   BEGIN
  1673.     (*$R-*)
  1674.     IF nextJN THEN
  1675.       RETURN which + 1
  1676.     ELSE
  1677.       RETURN which - 1
  1678.     END;
  1679.     (*$R=*)
  1680.   END next;
  1681.   (*$R- wegen Compiler-Bug*)
  1682.  
  1683. VAR u : BOOLEAN;
  1684. BEGIN
  1685.   which := next(which);
  1686.   u := UserBLK.ignoreRead;
  1687.   IF withShift THEN u := ~u END;
  1688.   ignoreReadMsgs := u;
  1689.   u := u OR UserBLK.ignoreFiltered;
  1690.   IF u & (winp # NIL) THEN
  1691.     ptr := winp;
  1692.     WHILE (which < ptr^.mess.MailAnz) & (which >= 0) & flagsNotOk(which) DO
  1693.       which := next(which);
  1694.     END;
  1695.   END;
  1696.   RETURN which
  1697. END grinNextMess;
  1698.  
  1699.   PROCEDURE hasOneInterestingMsg(mode : openMode; gr : CARDINAL; VAR nr : CARDINAL):BOOLEAN;
  1700.   BEGIN
  1701.     IF data.LastMsgOfGroup(gr) = dataSys.empty THEN RETURN FALSE END;
  1702.     (* Leere Gruppen haben keine interessanten Msgs.. *)
  1703.     CASE mode OF
  1704.       mFromBeginning    : nr := 0; RETURN TRUE
  1705.     | mFirstNew, mOther : nr := data.FirstNewMsg(gr); 
  1706.                           RETURN (nr <= data.LastMsgOfGroup(gr)) &
  1707.                                  (nr # dataSys.empty);
  1708.     | mUnread           : nr := data.unreadMsgPos(gr); 
  1709.                           RETURN data.unreadMsgCount(gr) # 0;
  1710.     | mLastPos          : nr := data.lastReadMsgOfGroup(gr);
  1711.                           RETURN nr # dataSys.empty;
  1712.     END;
  1713.   END hasOneInterestingMsg;
  1714.  
  1715.   PROCEDURE newGroup(ptr: oneWindowPtr; newWindow: BOOLEAN; withDial: BOOLEAN);
  1716.   (* Das ist so ein bischen gehackt.. *)
  1717.   VAR nr : CARDINAL; i : INTEGER; tree : ADDRESS; default : INTEGER;
  1718.       gz : CARDINAL; (* group-Z„hl *)
  1719.       lHdl: LONGCARD;
  1720.   BEGIN
  1721.     CASE ptr^.mode OF
  1722.       mFromBeginning    : default := MausTauschrsc.nextbegin;
  1723.     | mFirstNew, mOther : default := MausTauschrsc.nextnew;
  1724.     | mUnread           : default := MausTauschrsc.nextunread;
  1725.     | mLastPos          : default := MausTauschrsc.nextlast;
  1726.     END;
  1727.  
  1728.     IF ~autoNextGroup
  1729.     THEN
  1730.       IF withDial 
  1731.       THEN
  1732.         tree := MausTauschrsc.TreeAddr^[MausTauschrsc.nextgroup];
  1733.         (* IF ~mtDials.NewDial(tree) THEN MTE.noMemAlert(); RETURN END; *)
  1734.         mtUtils.InclFlag(tree, default, MagicAES.DEFAULT);
  1735.         
  1736.         ptr^.isLocked := TRUE;
  1737.         i := WinDials.WinDialDo (tree, -1);
  1738.         ptr^.isLocked := FALSE;
  1739.         i := INTEGER(BITSET(i) - {15});
  1740.         mtUtils.ExclState(tree, i, MagicAES.SELECTED);
  1741.         mtUtils.ExclFlag(tree, default, MagicAES.DEFAULT);
  1742.       ELSE
  1743.         i := default;
  1744.       END;
  1745.   
  1746.       CASE i OF
  1747.         MausTauschrsc.nextbegin  : ptr^.mode := mFromBeginning;
  1748.       | MausTauschrsc.nextnew    : ptr^.mode := mFirstNew; 
  1749.       | MausTauschrsc.nextunread : ptr^.mode := mUnread;
  1750.       | MausTauschrsc.nextlast   : ptr^.mode := mLastPos;
  1751.       ELSE 
  1752.         RETURN;
  1753.       END;
  1754.     ELSE
  1755.       IF autoNextPing 
  1756.       THEN
  1757.         CatGlobal.Bing (1);
  1758.       END;
  1759.     END;
  1760.  
  1761.   (* Zur n„chsten Gruppe mit neuen Nachrichten *)
  1762.     gz := ptr^.handle^.group;
  1763.     REPEAT
  1764.       gz := GroupSelect.NextGroupNumber(gz);
  1765.     UNTIL (gz = 0FFFFH) OR hasOneInterestingMsg(ptr^.mode, gz, nr);
  1766.     IF (gz # 0FFFFH) & hasOneInterestingMsg(ptr^.mode, gz, nr) THEN
  1767.       IF newWindow THEN
  1768.         v.int := grinOpenMessage(gz, nr, grinNextMess, 0, ptr^.mode);
  1769.       ELSE
  1770.         (*
  1771.         msgList.listUnlockWdw (ptr^.listHdl); 
  1772.         ptr^.listHdl := -1;
  1773.         ptr^.nextMsg := grinNextMess;
  1774.         *)
  1775.         IF ~msgList.listChangeGroup (ptr^.listHdl, ptr^.win, nr, gz, ptr^.mode)
  1776.         THEN
  1777.           ptr^.listHdl := 0;
  1778.           ptr^.nextMsg := grinNextMess;
  1779.         END;
  1780.         SwitchToNewGroup(gz, nr, ptr);
  1781.       END;
  1782.     ELSE
  1783.       v.int := mtAlerts.Alert (1, MTE.noMsg);
  1784.       IF v.int = 2 
  1785.       THEN
  1786.         lHdl := ptr^.listHdl;
  1787.         WdwManager.SendCloseWindow (ptr^.win);
  1788.         msgList.listCloseByHandle (lHdl);
  1789.       END;
  1790.     END;
  1791.   END newGroup;
  1792.  
  1793. PROCEDURE switch(ptr : oneWindowPtr; direction : dirType; newWindow : BOOLEAN; withShift : BOOLEAN);
  1794. VAR toWhere : CARDINAL; 
  1795.  
  1796.   PROCEDURE groupcom();
  1797.   VAR str : CatTypes.String255; id : CatTypes.Str1023Ptr; len : INTEGER; nr : CARDINAL;
  1798.       gr  : CatTypes.String255; grPtr: CatTypes.Str1023Ptr;
  1799.  
  1800.     PROCEDURE getIdNumber(ptr : data.OneGroupHandle):CARDINAL;
  1801.     BEGIN
  1802.       RETURN data.NumberOfID(ptr, id^);
  1803.     END getIdNumber;
  1804.  
  1805.   VAR gNr, 
  1806.       gAnz,
  1807.       which  : CARDINAL; 
  1808.       handle : handlePool.oneHandlePtr;
  1809.       found  : BOOLEAN;
  1810.  
  1811.       empty  : ARRAY[0..1] OF CHAR;
  1812.       break  : BOOLEAN;
  1813.   BEGIN
  1814.     empty[0] := 0C;
  1815.     IF CatEdit.GetTextLine(ptr^.win, 0, str, len) THEN
  1816.       IF PrepareIDnGroup(str, id, grPtr) THEN
  1817.         IF GroupSelect.GroupNumber(grPtr^, nr) THEN
  1818.           v.int := grinOpenWithProc(nr, getIdNumber,  grinNextMess, 0, mOther);
  1819.           RETURN
  1820.         ELSIF GroupSelect.NetGroupNumber(grPtr^, nr) THEN
  1821.           v.int := grinOpenWithProc(nr, getIdNumber,  grinNextMess, 0, mOther);
  1822.           RETURN
  1823.         ELSIF mtAlerts.Alert (1, MTE.noGroup) = 2 THEN
  1824.           RETURN;
  1825.           (* So, damit man bei defekter Gruppenangabe noch suchen kann. *)
  1826.         END;
  1827.       ELSIF PrepareID(ADR(str), id, v.char, v.card) THEN
  1828.         IF (mtAlerts.Alert (1, MTE.searchGroupCom) = 2) THEN
  1829.           RETURN
  1830.         END;
  1831.       ELSIF ((ptr^.mess.up = dataSys.notSaved) OR
  1832.              (ptr^.mess.up = dataSys.empty)) &
  1833.             (ptr^.mess.KommentierteID[0] = 0C) &
  1834.             (ptr^.mess.rid^[0] # 0C) & (* data sorgt fr Zuweisung auf emptyString! *)
  1835.             (ptr^.mess.MailNr > 0) &
  1836.             data.ComplexSearch(ptr^.handle^.Zugriff,
  1837.                                ptr^.mess.MailNr-1,                 (* StartNachricht         *)
  1838.                                {},
  1839.                                {},                              (* Zusammen Suchmaske     *)
  1840.                                ptr^.mess.rid^,              (* Zu suchender String    *)
  1841.                                empty, empty, empty,
  1842.                                SearchHelp.sUEBERALL, SearchHelp.sUEBERALL,  SearchHelp.sUEBERALL, SearchHelp.sUEBERALL,
  1843.                                SearchHelp.vUND, SearchHelp.vUND, SearchHelp.vUND, 
  1844.                                FALSE,                       (* grož=klein?            *)
  1845.                                {}, {},                      (* Zusammen Setzmaske     *)
  1846.                                data.SearchSet{data.inText, data.reverse},  (* Was machen?            *)
  1847.                                break,
  1848.                                nr)
  1849.       THEN
  1850.         v.int := grinOpenMessage(ptr^.handle^.group, nr, grinNextMess, 0, ptr^.mode);
  1851.         RETURN 
  1852.       ELSE
  1853.         RETURN
  1854.       END;
  1855.       IF ListHelp.SelectGroup (gr, gNr, FALSE, TRUE, TRUE, ListHelp.gsmGroupCom)
  1856.       THEN
  1857.         (* Wenn hier jetzt doch eine Gruppenangabe zur Verfgung steht, dann *)
  1858.         (* muž nur die Gruppe in <gr> gespeichert werden und dann funktioniert *)
  1859.         (* folgender Aufruf: *)
  1860.         IF gr[0] # "" THEN
  1861.           IF handlePool.GetOneDatahandle(gNr, handle) THEN
  1862.             which := data.NumberOfID(handle^.Zugriff, id^);
  1863.             IF data.error = data.noError THEN
  1864.               v.int := grinOpenWithProc(gNr, getIdNumber, grinNextMess, 0, mOther);
  1865.               found := TRUE;
  1866.             ELSE
  1867.               (* Fehlermeldung *)
  1868.               MTE.info(MTE.noFound);
  1869.             END;
  1870.             handlePool.FreeOneDataHandle(handle);
  1871.           END;
  1872.         ELSE
  1873.           gNr := 0;
  1874.           v.bool := GroupSelect.GroupNumber('$&%$&%$/&/&%&/$&/Ý$/&$/&', gAnz);
  1875.           (* Wenn es eine Gruppe mit diesem Namen gibt, sprechen wir uns wieder :-) *)
  1876.           (* Geht auch besser, aber das war hier der einfachste Hack.. *)
  1877.           found := FALSE;
  1878.           WHILE (gNr < gAnz) & ~found & ~stopSearch() DO
  1879.             IF handlePool.GetOneDatahandle(gNr, handle) THEN
  1880.               which := data.NumberOfID(handle^.Zugriff, id^);
  1881.               IF data.error = data.noError THEN
  1882.                 v.int := grinOpenWithProc(gNr, getIdNumber, grinNextMess, 0, mOther);
  1883.                 found := TRUE;
  1884.               END;
  1885.               handlePool.FreeOneDataHandle(handle);
  1886.             END;
  1887.             INC(gNr);
  1888.             CatGlobal.busyMouse();
  1889.           END;
  1890.           mtAppl.MouseArrow();
  1891.         END;
  1892.         IF ~found THEN 
  1893.           CatGlobal.Bing (7);         (* Bing *)
  1894.         END;
  1895.       END;
  1896.     END;
  1897.   END groupcom;
  1898.  
  1899. BEGIN
  1900.   IF dirPossible(ptr, direction, withShift) THEN
  1901.     IF UserBLK.AutoUndo THEN 
  1902.       toWhere := ptr^.lastPos; 
  1903.       setReadFlag(ptr);
  1904.     ELSE 
  1905.       toWhere := ptr^.mess.MailNr;
  1906.     END;
  1907.     CASE direction OF
  1908.       dPrevMess  : IF ~withShift THEN
  1909.                      toWhere := ptr^.nextMsg (toWhere, FALSE, withShift, ptr^.listHdl, ptr);
  1910.                    ELSE
  1911.                    (* Unterscheiden, ob die externe Routine aufgerufen wird -> Listfenster *)
  1912.                    (* dann soll mit shift die normale Routine, ohne Gelesene ignorieren    *)
  1913.                    (* aufgerufen werden *)
  1914.                      IF ptr^.nextMsg = grinNextMess THEN
  1915.                        toWhere := grinNextMess (toWhere, FALSE, withShift, 0, ptr);
  1916.                      ELSE
  1917.                        toWhere := grinNextMess (toWhere, FALSE, withShift, 0, NIL);
  1918.                      END;
  1919.                    END;
  1920.     | dNextMess  : IF ~withShift THEN
  1921.                      toWhere := ptr^.nextMsg (toWhere, TRUE, withShift, ptr^.listHdl, ptr)
  1922.                    ELSE
  1923.                    (* Unterscheiden, ob die externe Routine aufgerufen wird -> Listfenster *)
  1924.                    (* dann soll mit shift die normale Routine, ohne Gelesene ignorieren    *)
  1925.                    (* aufgerufen werden *)
  1926.                      IF ptr^.nextMsg = grinNextMess THEN
  1927.                        toWhere := grinNextMess (toWhere, TRUE, withShift, 0, ptr);
  1928.                      ELSE
  1929.                        toWhere := grinNextMess (toWhere, TRUE, withShift, 0, NIL);
  1930.                      END;
  1931.                    END;
  1932.     | dUpMess    : toWhere := ptr^.mess.up;
  1933.     | dDownMess  : toWhere := ptr^.mess.down;
  1934.     | dLeftMess  : toWhere := ptr^.mess.left;
  1935.     | dRightMess : toWhere := ptr^.mess.right;
  1936.     END;
  1937.     IF (toWhere = 0FFFFH) OR (toWhere >= ptr^.mess.MailAnz) THEN
  1938.       IF direction = dNextMess THEN newGroup(ptr, newWindow, TRUE) END;
  1939.     ELSE
  1940.       IF newWindow THEN
  1941.         v.int := grinOpenMessage(ptr^.handle^.group, toWhere, grinNextMess, 0, ptr^.mode);
  1942.       ELSE
  1943.         SwitchTo(ptr, toWhere, direction, FALSE);
  1944.       END;
  1945.     END;
  1946.   ELSIF direction = dNextMess THEN
  1947.     newGroup(ptr, newWindow, TRUE);
  1948.   ELSIF direction = dUpMess THEN
  1949.   (* Hier fr gruppenbergreifende Kommentarverkettung. *)
  1950.   (* .. und fr die Suche nach Usenet-Verkettung.       *)
  1951.     groupcom();
  1952.   END;
  1953. END switch;
  1954.  
  1955. PROCEDURE hiddenFeature(wdw: INTEGER; feature: INTEGER);
  1956. (* Setzt alle nachfolgenden Nachrichten in der Gruppe auf Gelesen und 
  1957.  * geht mit dem aktuellen  Lesemodus ohne Nachfrage zur n„chsten Gruppe
  1958.  * Modus 1: Alle Nachrichten auf Gelesen setzen, n„chste Gruppe
  1959.  * Modus 2: Einfach zur n„chsten Gruppe
  1960.  *)
  1961. VAR ptr : oneWindowPtr; 
  1962.     start: CARDINAL;
  1963.     i   : CARDINAL;
  1964.     flags : BITSET;
  1965.   
  1966.   PROCEDURE new(old : BITSET):BITSET; BEGIN RETURN ptr^.mess.StatusBits; END new;
  1967. BEGIN
  1968.   IF (feature # 0) & (feature # 1) & (feature # 2)THEN RETURN END;
  1969.   (* Erstmal alles auf Gelesen setzen *)
  1970.   IF handlePool.FindEntry(ADR(wdw), FindWinCond, windows, ptr) THEN
  1971.     (* Fenster ist da, alle auf Gelesen setzen *)
  1972.     INCL(ptr^.mess.StatusBits, dataSys.bGelesen);
  1973.     data.SetBits(ptr^.handle^.Zugriff, ptr^.mess.MailNr, ptr^.mess.StatusBits);
  1974.     InternalChange(ptr, new);
  1975.     IF feature = 0
  1976.     THEN
  1977.       start := ptr^.mess.MailNr
  1978.     ELSIF feature = 1
  1979.     THEN
  1980.       start := 0;
  1981.     END;
  1982.     IF feature < 2 THEN
  1983.       FOR i := start TO ptr^.mess.MailAnz-1 DO
  1984.         data.ReadState (ptr^.handle^.Zugriff, i, flags);
  1985.         IF ~(dataSys.bGelesen IN flags) 
  1986.         THEN
  1987.           INCL (flags, dataSys.bGelesen);
  1988.           data.SetBits (ptr^.handle^.Zugriff, i, flags);
  1989.         END;
  1990.       END;
  1991.     END;
  1992.     (* So, und jetzt zur n„chsten Gruppe *)
  1993.     newGroup (ptr, FALSE, FALSE);
  1994.   END;
  1995. END hiddenFeature;
  1996.  
  1997. (*-- Clicks in den Statusbereich/ Status invertieren --------------*)
  1998.  
  1999. PROCEDURE InternalInvert(ptr : oneWindowPtr; whichState : CARDINAL);
  2000. (* ptr : Das Fenster, das die Žnderung hervorgerufen hat *)
  2001. (* Anschliežend werden alle anderen Fenster durchsucht, ob sie dieselbe Msg *)
  2002. (* aus dieser Gruppe darstellen und dort auch der Status gesetzt            *)
  2003. VAR newFlags : BITSET;
  2004.  
  2005.   PROCEDURE new(old : BITSET):BITSET;
  2006.   BEGIN
  2007.     RETURN newFlags;
  2008.   END new;
  2009.  
  2010. BEGIN
  2011.   WITH ptr^ DO
  2012.     (* neue Flags berechnen *)
  2013.     newFlags := mess.StatusBits;
  2014.     IF whichState IN newFlags THEN
  2015.       EXCL(newFlags, whichState);
  2016.     ELSE
  2017.       INCL(newFlags, whichState);
  2018.     END;
  2019.     InternalChange(ptr, new);
  2020.   END;
  2021. END InternalInvert;
  2022.  
  2023. PROCEDURE ClickInvert(ptr : oneWindowPtr; mx, my : INTEGER);
  2024. VAR pixelPerState : INTEGER; state : CARDINAL;
  2025. BEGIN
  2026.   DEC(mx, infoAdr^[MausTauschrsc.wstati].obX);
  2027.   DEC(mx, infoAdr^[0].obX);
  2028.   pixelPerState := infoAdr^[MausTauschrsc.wstati].obWidth DIV StateAnz;
  2029.   state := CARDINAL(mx DIV pixelPerState);
  2030.   InternalInvert(ptr, state);
  2031. END ClickInvert;
  2032.  
  2033. (*--- eigene Infozeile verwalten --------------*)
  2034.  
  2035. PROCEDURE InitPopup();
  2036.   VAR str : ARRAY [0..40] OF CHAR;
  2037. BEGIN
  2038.   mtUtils.ObjcString (flagPop, MausTauschrsc.popuflg1, str);
  2039.   CatGlobal.MakeStr (UserBLK.ustr1, str);
  2040.   mtUtils.SetObjcString (flagPop, MausTauschrsc.popuflg1, str);
  2041.   mtUtils.ObjcString (flagPop, MausTauschrsc.popuflg2, str);
  2042.   CatGlobal.MakeStr (UserBLK.ustr2, str);
  2043.   mtUtils.SetObjcString (flagPop, MausTauschrsc.popuflg2, str);
  2044. END InitPopup;
  2045.  
  2046. PROCEDURE InitRsc();
  2047. BEGIN
  2048.   infoAdr := MausTauschrsc.TreeAddr^[MausTauschrsc.grsteuer]; 
  2049.   addInfo := MausTauschrsc.TreeAddr^[MausTauschrsc.addinfo]; 
  2050.   flagPop := MausTauschrsc.TreeAddr^[MausTauschrsc.flagpop];
  2051. END InitRsc;
  2052.  
  2053. PROCEDURE grinKey(win    : INTEGER; VAR scan, c :  CHAR;
  2054.                   VAR kstate : BITSET; VAR moreChars : BOOLEAN):BOOLEAN;FORWARD;
  2055.  
  2056. PROCEDURE CheckPersonal (ptr : oneWindowPtr; VAR c : CHAR; kstate: BITSET;
  2057.                          VAR done: BOOLEAN):BOOLEAN;
  2058.   (* gibt an, ob der Buchstabe nicht ok ist *)
  2059.   (* done gibt an, ob der Tastendruck behandelt wurde *)
  2060. BEGIN
  2061.   done := FALSE;
  2062.   IF CatGlobal.WithCtrl (kstate) OR CatGlobal.WithAlt (kstate) THEN RETURN FALSE END;
  2063.   IF  (ptr^.handle^.group = dataSys.private) & 
  2064.       (~ptr^.mess.EigeneNachricht) THEN
  2065.     IF (ptr^.mess.Status = 'N') 
  2066.     THEN
  2067.       (* Nur in diesem Fall kann eine Eingabe nicht Ok sein! *)
  2068.       
  2069.       (* Nicht gelesene und Zurckgestellte behandeln,  *)
  2070.       (* letztere nur wenn nicht nochmal zurckgestellt *)
  2071.       IF (c = 'N') OR (c = 'Z') THEN
  2072.         IF c = 'N' THEN
  2073.           SendState(ptr^.mess.MailID^, 'G');
  2074.           changeState(ptr, 'G');
  2075.           done := TRUE;
  2076.         ELSIF c = 'Z' THEN
  2077.           SendState(ptr^.mess.MailID^, 'Z');
  2078.           changeState(ptr, c);
  2079.           done := TRUE;
  2080.           c := 'N';
  2081.         END;
  2082.         RETURN FALSE;
  2083.       ELSE
  2084.         RETURN TRUE
  2085.       END
  2086.     ELSIF (ptr^.mess.Status = 'Z') & (c = 'N') THEN
  2087.       SendState(ptr^.mess.MailID^, 'G');
  2088.       changeState(ptr, 'G');
  2089.       done := TRUE;
  2090.     ELSIF (ptr^.mess.Status = 'G') & (c = 'Z') THEN
  2091.       SendState(ptr^.mess.MailID^, 'Z');
  2092.       changeState(ptr, 'Z');
  2093.       c := 'N';
  2094.       done := TRUE;
  2095.     END;
  2096.   END;
  2097.   RETURN FALSE;
  2098. END CheckPersonal;
  2099.  
  2100. (* Bewegung zur n„chsten/vorherigen in der privaten Gruppe 
  2101.  *)
  2102. PROCEDURE NextPrevPrivate (ptr: oneWindowPtr; scan, char : CHAR;
  2103.                            kstate: BITSET): BOOLEAN;
  2104. VAR
  2105.   chkPers   : BOOLEAN;
  2106.   bDone     : BOOLEAN;
  2107. BEGIN
  2108.   chkPers := CheckPersonal (ptr, char, kstate, bDone);
  2109.   IF chkPers & restrictedMoves
  2110.   THEN
  2111.     CASE mtAlerts.Alert (1, "[1][CAT:|Neue pers”nliche Nachricht:|(B)eantworten|(Z)urckstellen|(N)icht antworten][[Beantworten|[Zurckstellen|[Nicht antworten]") OF
  2112.       1 : char := 'B'; |
  2113.       2 : char := 'Z'; |
  2114.       3 : char := 'N'; |
  2115.     ELSE
  2116.     END;
  2117.     scan := 0C;
  2118.     kstate := {};
  2119.     RETURN grinKey (ptr^.win, scan, char, kstate, bDone);
  2120.   END;
  2121.   RETURN FALSE;
  2122. END NextPrevPrivate;
  2123.  
  2124. PROCEDURE WriteToClip (REF str : ARRAY OF CHAR);
  2125.   CONST scrapName = 'SCRAP.TXT';
  2126.   VAR name : ARRAY [0..255] OF CHAR;
  2127.       hdl  : INTEGER;
  2128.       cnt  : LONGCARD;
  2129. BEGIN
  2130.   IF ~Clip.GetScrap (name) THEN RETURN END;
  2131.   MagicStrings.Append (scrapName, name);
  2132.   hdl := MagicDOS.Fcreate (name, {});
  2133.   IF hdl < 0 THEN RETURN END;
  2134.   cnt := LENGTH (str);
  2135.   MagicDOS.Fwrite (hdl, cnt, CADR(str));
  2136.   hdl := MagicDOS.Fclose (hdl);
  2137.   Clip.ScrapWritten({MagicAES.SCFTEXT}, ".TXT");
  2138.   IF ~Clip.GetScrap (name) THEN RETURN END;
  2139.   Protokoll.SendPathUpdate (name);
  2140. END WriteToClip;
  2141.  
  2142. TYPE ddExt = ARRAY [0..3] OF CHAR;
  2143.  
  2144. CONST   grinExt = ".FLT";
  2145.         grinDDName = "CAT Filterinformation";
  2146.  
  2147. PROCEDURE grinDDGetMaxExts (wdw: INTEGER): INTEGER;
  2148.   VAR ptr : oneWindowPtr;
  2149. BEGIN
  2150.   IF handlePool.FindEntry(ADR(wdw), FindWinCond, windows, ptr) THEN
  2151.     RETURN 1;
  2152.   END;
  2153.   RETURN 0;
  2154. END grinDDGetMaxExts;
  2155.  
  2156. PROCEDURE grinDDGetExt (wdw: INTEGER; mode: INTEGER; VAR ext: ARRAY OF CHAR): BOOLEAN;
  2157.   VAR ptr : oneWindowPtr;
  2158. BEGIN
  2159.   IF handlePool.FindEntry(ADR(wdw), FindWinCond, windows, ptr) THEN
  2160.     IF mode = WdwManager.HDRFIRST
  2161.     THEN
  2162.       MagicStrings.Assign (grinExt, ext);
  2163.       RETURN TRUE;
  2164.     END;
  2165.   END;
  2166.   RETURN FALSE;
  2167. END grinDDGetExt;
  2168.  
  2169. PROCEDURE grinDDGetExtName (wdw: INTEGER; idx: INTEGER; VAR name: ARRAY OF CHAR);
  2170.   VAR ptr : oneWindowPtr;
  2171. BEGIN
  2172.   MagicStrings.Assign ("", name);
  2173.   IF handlePool.FindEntry(ADR(wdw), FindWinCond, windows, ptr) THEN
  2174.     IF idx = 0
  2175.     THEN
  2176.       MagicStrings.Assign (grinDDName, name);
  2177.     END;
  2178.   END;
  2179. END grinDDGetExtName;
  2180.  
  2181. PROCEDURE grinDDGetSize (wdw: INTEGER; idx: INTEGER; VAR size: LONGCARD);
  2182.   VAR ptr : oneWindowPtr;
  2183. BEGIN
  2184.   size := 0;
  2185.   IF handlePool.FindEntry(ADR(wdw), FindWinCond, windows, ptr) THEN
  2186.     (* Wir bergeben folgendes: 
  2187.      * From: Absender, 256 Zeichen
  2188.      * TAB
  2189.      * Topic: Betreff, 256 Zeichen
  2190.      * TAB
  2191.      * Group: Gruppe, 256 Zeichen
  2192.      * TAB
  2193.      *)
  2194.     size := LENGTH (cFrom) + LENGTH (cSubject) + LENGTH (cGroup) + 771 (* 256*3 + 3 *);
  2195.   END;
  2196. END grinDDGetSize;
  2197.  
  2198. PROCEDURE grinDDGetData (wdw: INTEGER; idx: INTEGER; VAR data: ADDRESS);
  2199.   VAR ptr  : oneWindowPtr;
  2200.       size : LONGCARD;
  2201.       pos  : LONGCARD;
  2202.       text : CatTypes.LargeTextPtr;
  2203.       k    : LONGCARD;
  2204.       gName: CatTypes.String255;
  2205. BEGIN
  2206.   data := NIL;
  2207.   IF handlePool.FindEntry(ADR(wdw), FindWinCond, windows, ptr) THEN
  2208.     WITH ptr^ DO
  2209.       grinDDGetSize (wdw, idx, size);
  2210.       IF (size > 0)
  2211.       THEN
  2212.         ALLOCATE (data, size);
  2213.         IF data = NIL
  2214.         THEN
  2215.           RETURN
  2216.         END;
  2217.         text := data;
  2218.         (* Jetzt daten Kopieren *)
  2219.         pos := 0;
  2220.         Block.Copy (CADR(cFrom), LENGTH (cFrom), data+ADDRESS(pos));
  2221.         INC (pos, LENGTH (cFrom));
  2222.         (* Feld kopieren *)
  2223.         FOR k := 0 TO 255 DO
  2224.           text^[pos+k] := ' ';
  2225.         END;
  2226.         (* Absender kopieren *)
  2227.         IF (mess.Absender # NIL) & (ddObjc = MausTauschrsc.wvon)
  2228.         THEN 
  2229.           Block.Copy (mess.Absender, LENGTH (mess.Absender^), data+ADDRESS(pos));
  2230.         END;
  2231.         INC (pos, 256);
  2232.         Block.Copy (CADR(cTAB), 1, data+ADDRESS(pos));
  2233.         INC (pos);
  2234.         Block.Copy (CADR(cSubject), LENGTH (cSubject), data+ADDRESS(pos));
  2235.         INC (pos, LENGTH (cSubject));
  2236.         (* zweites Feld kopieren *)
  2237.         FOR k := 0 TO 255 DO
  2238.           text^[pos+k] := ' ';
  2239.         END;
  2240.         IF (mess.Betreff # NIL) & (ddObjc = MausTauschrsc.wwegen)
  2241.         THEN 
  2242.           Block.Copy (mess.Betreff, LENGTH (mess.Betreff^), data+ADDRESS(pos));
  2243.         END;
  2244.         INC (pos, 256);
  2245.         Block.Copy (CADR(cTAB), 1, data+ADDRESS(pos));
  2246.         INC (pos);
  2247.         (* Jetzt noch Gruppe anh„ngen *)
  2248.         Block.Copy (CADR(cGroup), LENGTH (cGroup), data+ADDRESS(pos));
  2249.         INC (pos, LENGTH (cGroup));
  2250.         (* Feld kopieren *)
  2251.         FOR k := 0 TO 255 DO
  2252.           text^[pos+k] := ' ';
  2253.         END;
  2254.         (* Gruppennamen kopieren *)
  2255.         GroupSelect.GroupName (mess.Gruppe, gName);
  2256.         Block.Copy (ADR(gName), LENGTH (gName), data+ADDRESS(pos));
  2257.         INC (pos, 256);
  2258.         Block.Copy (CADR(cTAB), 1, data+ADDRESS(pos));
  2259.       END;
  2260.     END;
  2261.   END;
  2262. END grinDDGetData;
  2263.  
  2264. (* Prozeduren, die an CatEdit bergeben werden *)
  2265. PROCEDURE click(win, vdiHdl, mx, my : INTEGER;
  2266.                 kstate : BITSET; work : GrafBase.Rectangle);
  2267. (* Wird bei Klick in das entsprechende Fenster aufgerufen *)
  2268. VAR obj         : INTEGER; 
  2269.     ptr         : oneWindowPtr; 
  2270.     nw          : BOOLEAN; (* "NewWindow" *)
  2271.     withShift   : BOOLEAN;
  2272.     x, y, i     : INTEGER;
  2273.     res         : INTEGER; 
  2274.     s, c        : CHAR; 
  2275.     b           : BITSET; 
  2276.     more        : BOOLEAN;
  2277.     popStr      : CatTypes.String255;
  2278.     chkPers     : BOOLEAN;
  2279.     newCh       : CHAR;
  2280.     buts        : BITSET;
  2281.     str         : CatTypes.String255;
  2282.     oldX,
  2283.     oldY        : INTEGER;
  2284.     hdl         : INTEGER;
  2285.     xDiff,
  2286.     yDiff       : INTEGER;
  2287.     (* Drag&Drop *)
  2288.     size        : LONGCARD;
  2289.     data        : ADDRESS;
  2290.     siz         : CARDINAL;
  2291.     apId        : INTEGER;
  2292. BEGIN
  2293.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) THEN
  2294.     IF ptr^.inEvent THEN RETURN END;
  2295.     ptr^.inEvent := TRUE;
  2296.     AdjustPosition(work.x, work.y, work.w);
  2297.     obj := MagicAES.ObjcFind(infoAdr, 0, MAX(INTEGER), mx, my);
  2298.     nw := MagicAES.KCTRL IN kstate;
  2299.     withShift := (MagicAES.KLSHIFT IN kstate) OR (MagicAES.KRSHIFT IN kstate);
  2300.     newCh := "";
  2301.     (*
  2302.     IF (obj # MausTauschrsc.wvon)
  2303.     &  (obj # MausTauschrsc.wwegen)
  2304.     THEN
  2305.       mtUtils.Bounce();
  2306.     END;
  2307.     *)
  2308.     (* chkPers := CheckPersonal (ptr, newCh, kstate, v.bool); *)
  2309.     IF    obj = MausTauschrsc.wprevmess  THEN 
  2310.       (* Prfen, ob Restricted Mode *)
  2311.       IF NextPrevPrivate (ptr, 0C, 'L', {})
  2312.       THEN
  2313.         ptr^.inEvent := FALSE;
  2314.         RETURN 
  2315.       END;
  2316.       IF withShift THEN
  2317.         IF nw THEN
  2318.           v.int := grinOpenMessage(ptr^.handle^.group, 0, grinNextMess, 0, ptr^.mode);
  2319.         ELSE
  2320.           SwitchTo (ptr, 0, dJump, FALSE) 
  2321.         END;
  2322.       ELSE
  2323.         switch(ptr, dPrevMess, nw, withShift)
  2324.       END;
  2325.     ELSIF obj = MausTauschrsc.wnextmess  THEN 
  2326.       IF NextPrevPrivate (ptr, spaceScan, 0C, {})
  2327.       THEN
  2328.         ptr^.inEvent := FALSE;
  2329.         RETURN 
  2330.       END;
  2331.       IF withShift THEN 
  2332.         IF nw THEN
  2333.           v.int := grinOpenMessage(ptr^.handle^.group, 0, grinNextMess, 0, ptr^.mode);
  2334.         ELSE
  2335.           SwitchTo (ptr, ptr^.mess.MailAnz-1, dJump, FALSE)
  2336.         END;
  2337.       ELSE
  2338.         switch(ptr, dNextMess, nw, withShift)
  2339.       END;
  2340.     ELSIF obj = MausTauschrsc.wupmess    THEN switch(ptr, dUpMess,   nw, withShift)
  2341.     ELSIF obj = MausTauschrsc.wdownmess  THEN switch(ptr, dDownMess, nw, withShift)
  2342.     ELSIF obj = MausTauschrsc.wleftmess  THEN switch(ptr, dLeftMess, nw, withShift)
  2343.     ELSIF obj = MausTauschrsc.wrightmess THEN switch(ptr, dRightMess,nw, withShift)
  2344.     ELSIF obj = MausTauschrsc.wstati     THEN ClickInvert(ptr, mx, my);
  2345.     ELSIF obj = MausTauschrsc.waction    THEN 
  2346.       mtUtils.ObjcPos (infoAdr, obj, x, y);
  2347.       IF ptr^.handle^.group = dataSys.private
  2348.       THEN
  2349.         popStr := " Beantworten       'B'| Kopieren          'C'| Gruppenkommentar  'G'| L”schen           'X'| Weitergeben       'W'| Nicht beantworten 'N'| Zurckstellen     'Z'| Wiedervorlegen    'R'";
  2350.         res := mtPopups.PosPopup(x, y, popStr, '');
  2351.         CASE res OF
  2352.          -1 : ptr^.inEvent := FALSE;
  2353.               RETURN;
  2354.         | 0 : c := 'b';
  2355.         | 1 : c := 'c'; 
  2356.         | 2 : c := 'g';
  2357.         | 3 : c := 'x';
  2358.         | 4 : c := 'w';
  2359.         | 5 : c := 'n';
  2360.         | 6 : c := 'z';
  2361.         | 7 : c := 'r';
  2362.         ELSE
  2363.           ptr^.inEvent := FALSE;
  2364.           RETURN
  2365.         END;
  2366.       ELSE
  2367.         popStr := " Beantworten      'B'| Kommentieren     'K'| Gruppenkommentar 'G'| L”schen          'X'| Wiedervorlegen   'R'";
  2368.         res := mtPopups.PosPopup(x, y, popStr, '');
  2369.         CASE res OF
  2370.          -1 : ptr^.inEvent := FALSE;
  2371.               RETURN;
  2372.         | 0 : c := 'b';
  2373.         | 1 : c := 'k';
  2374.         | 2 : c := 'g';
  2375.         | 3 : c := 'x';
  2376.         | 4 : c := 'r';
  2377.         ELSE
  2378.           ptr^.inEvent := FALSE;
  2379.           RETURN
  2380.         END;
  2381.       END;
  2382.       s := 0C; b := {}; more := FALSE;
  2383.       v.bool := grinKey (win, s, c, b, more);
  2384.     ELSIF obj = MausTauschrsc.winfo      THEN 
  2385.       c := 'I'; s := 0C; b := {}; more := FALSE;
  2386.       v.bool := grinKey (win, s, c, b, more);
  2387.     ELSIF obj = MausTauschrsc.wtree THEN
  2388.       mtUtils.InclState (infoAdr, obj, MagicAES.SELECTED);
  2389.       ObjcDraw (ptr^.win, obj, 1);
  2390.       treeList.treeOpen (ptr^.mess.Gruppe, ptr^.mess.MailNr, ptr^.win);
  2391.       mtUtils.ExclState (infoAdr, obj, MagicAES.SELECTED);
  2392.       ObjcDraw (ptr^.win, obj, 1);
  2393.     ELSIF obj = MausTauschrsc.wpict THEN
  2394.       mtUtils.InclState (infoAdr, obj, MagicAES.SELECTED);
  2395.       ObjcDraw (ptr^.win, obj, 1);
  2396.       ActualName (ptr^.win, popStr);
  2397.       IF CatGlobal.WithShift (kstate)
  2398.       THEN
  2399.         WriteToClip (popStr);
  2400.       ELSE
  2401.         Protokoll.SendHelp (popStr);
  2402.       END;
  2403.       mtUtils.ExclState (infoAdr, obj, MagicAES.SELECTED);
  2404.       ObjcDraw (ptr^.win, obj, 1);
  2405.     ELSIF obj = MausTauschrsc.wlist THEN
  2406.       mtUtils.InclState (infoAdr, obj, MagicAES.SELECTED);
  2407.       ObjcDraw (ptr^.win, obj, 1);
  2408.       s := escScan; b := kstate; c := 0C; more := FALSE;
  2409.       v.bool := grinKey(win, s, c, b, more);
  2410.       mtUtils.ExclState (infoAdr, obj, MagicAES.SELECTED);
  2411.       ObjcDraw (ptr^.win, obj, 1);
  2412.     ELSIF obj = MausTauschrsc.return THEN SwitchTo(ptr, ptr^.lastPos, dReturn, FALSE);
  2413.     ELSIF obj = MausTauschrsc.wpop THEN
  2414.       mtUtils.ObjcPos (infoAdr, obj, x, y);
  2415.       FOR i := dataSys.bGelesen TO dataSys.bVererben DO
  2416.         mtUtils.SetState (flagPop, i+1, MagicAES.CHECKED, i IN ptr^.mess.StatusBits);
  2417.       END;
  2418.       InitPopup();
  2419.       res := mtPopups.TreePopup (flagPop, x, y, 0) ;
  2420.       IF res > 0 THEN
  2421.         InternalInvert(ptr, res-1);
  2422.       END;
  2423.     ELSIF (obj = MausTauschrsc.wvon)
  2424.        OR (obj = MausTauschrsc.wwegen)
  2425.     THEN
  2426.       (* Drag&Drop von Name oder Betreff *)
  2427.       mtUtils.InclState (infoAdr, obj, MagicAES.SELECTED);
  2428.       ObjcDraw (ptr^.win, obj, 1);
  2429.       (* String holen *)
  2430.       mtUtils.ObjcString (infoAdr, obj, str);
  2431.       IF LENGTH (str) > 30
  2432.       THEN
  2433.         str[28] := '.';
  2434.         str[29] := '.';
  2435.         str[30] := '.';
  2436.         str[31] := 0C;
  2437.       END;
  2438.       (* Begin Drag&Drop *)
  2439.       hdl := mtAppl.VDIHandle;
  2440.       oldX := mx; 
  2441.       oldY := my;
  2442.       mtUtils.ObjcArea (infoAdr, obj, v.r);
  2443.       xDiff := mx - v.r[0];
  2444.       yDiff := my - v.r[1] - mtAppl.CharHeight;
  2445.       MagicAES.WindUpdate (MagicAES.BEGMCTRL);
  2446.       mtAppl.StoreMouse();
  2447.       mtAppl.MouseHand();
  2448.       v.int := MagicVDI.SetWritemode (hdl, MagicVDI.XOR);
  2449.       mtAppl.MouseOff();
  2450.       MagicVDI.SetTextalignment (hdl, 0, 3, v.int, v.int);
  2451.       v.int := MagicVDI.SetCharpoints (hdl, 10, v.int, v.int, v.int, v.int);
  2452.       VDIStandards.Text (FALSE, hdl, mx - xDiff, my - yDiff, str);
  2453.       mtAppl.MouseOn();
  2454.       REPEAT
  2455.         MagicAES.GrafMkstate (mx, my, buts, kstate);
  2456.         IF (mx # oldX) OR (my # oldY)
  2457.         THEN
  2458.           mtAppl.MouseOff();
  2459.           VDIStandards.Text (FALSE, hdl, oldX - xDiff, oldY - yDiff, str);
  2460.           VDIStandards.Text (FALSE, hdl, mx - xDiff, my - yDiff, str);
  2461.           oldX := mx;  
  2462.           oldY := my; 
  2463.           mtAppl.MouseOn();
  2464.         END;
  2465.       UNTIL ~(0 IN buts);
  2466.       (* Text wegzeichnen *)
  2467.       mtAppl.MouseOff();
  2468.       VDIStandards.Text (FALSE, hdl, oldX - xDiff, oldY - yDiff, str);
  2469.       mtAppl.MouseOn();
  2470.       v.int := MagicVDI.SetWritemode (hdl, MagicVDI.REPLACE);
  2471.       mtAppl.RestoreMouse();
  2472.       MagicAES.WindUpdate (MagicAES.ENDMCTRL);
  2473.       (* Window suchen *)
  2474.       hdl := MagicAES.WindFind (mx, my);
  2475.       IF hdl # win
  2476.       THEN
  2477.         (* Check if block is marked in editor *)
  2478.         IF CatEdit.BlockIsMarked (win)
  2479.         THEN
  2480.           (* Wir mssen den Block l”schen, denn sonst ginge das D&D
  2481.            * ber den Block
  2482.            *)
  2483.           CatEdit.ClearBlock (win);
  2484.         END;
  2485.         ptr^.ddObjc := obj;
  2486.         MagicAES.WindUpdate (MagicAES.ENDUPDATE);
  2487.         IF ~WdwManager.WdwDDServe (win, mx, my, kstate)
  2488.         THEN
  2489.           (* Das ganze per Message verschicken *)
  2490.           IF WdwManager.GetApId (hdl, apId)
  2491.           THEN
  2492.             grinDDGetSize (win, 0, size);
  2493.             grinDDGetData (win, 0, data);
  2494.             siz := SHORT (size);
  2495.             v.bool := Protokoll.Send2Filter (apId, siz, data);
  2496.           END;
  2497.         END;
  2498.         MagicAES.WindUpdate (MagicAES.BEGUPDATE);
  2499.       END;
  2500.       (* Ende Drag&Drop *)
  2501.       mtUtils.ExclState (infoAdr, obj, MagicAES.SELECTED);
  2502.       ObjcDraw (ptr^.win, obj, 1);
  2503.     END;
  2504.     ptr^.inEvent := FALSE;
  2505.   END;
  2506. END click;
  2507.  
  2508. PROCEDURE grinTop (win : INTEGER); 
  2509.   VAR ptr : oneWindowPtr;   
  2510. BEGIN
  2511.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) THEN
  2512.     VDIStandards.StatusEnable (TRUE);
  2513.     VDIStandards.StatusCheck(ptr^.mess.StatusBits);
  2514.     Protokoll.SendNewMsgInWdw();
  2515.   END;
  2516. END grinTop;
  2517.  
  2518. PROCEDURE grinUntop (win : INTEGER);
  2519. BEGIN
  2520.   VDIStandards.StatusEnable(FALSE);
  2521. END grinUntop;
  2522.  
  2523. PROCEDURE getRect(win          : INTEGER;
  2524.                   editWork     : GrafBase.Rectangle;
  2525.               VAR userRect,
  2526.                   editWorkRect : GrafBase.Rectangle);
  2527. (* Wird aufgerufen, um die Ausmaže des am oberen Fensterrandes liegenden Objektes festzustellen *)
  2528. VAR ptr : oneWindowPtr;
  2529.     treeRect : GrafBase.Rectangle;
  2530.     varName  : ARRAY [0..255] OF CHAR;
  2531.     full     : GrafBase.Rectangle;
  2532.     number   : INTEGER;
  2533. BEGIN
  2534.   editWorkRect := editWork;
  2535.   mtUtils.CalcArea (infoAdr, 0, treeRect);
  2536.   userRect := GrafBase.Rect(editWork.x, editWork.y, editWork.w, treeRect.h-1 );
  2537.   INC(editWorkRect.y, userRect.h);
  2538.   DEC(editWorkRect.h, userRect.h);
  2539.   (* Aufpassen, falls es zu klein wird *)
  2540.   IF (win >= 0) & handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) THEN
  2541.     number := ptr^.number;
  2542.     Strings.Concat (cMsgWindow, StrConv.IntToStr (number, 0), varName, v.bool);
  2543.     WdwManager.GetWdwSize  (win, full); (* Gr”že des Fensters abfragen *)
  2544.     v.bool := ConfVars.SetConfigRect (varName, full);
  2545.   END;
  2546. END getRect;
  2547.  
  2548. PROCEDURE draw(win, vdiHdl : INTEGER; wdwWork, clip : GrafBase.Rectangle;
  2549.                textCol, backCol : INTEGER);
  2550. (* Wird aufgerufen, um den Objektbereich neuzuzeichnen *)
  2551. VAR ptr : oneWindowPtr;
  2552. BEGIN
  2553.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) THEN
  2554.     WITH wdwWork DO
  2555.       AdjustPosition(x, y, w);
  2556.     END;
  2557.     MakeInfoline(ptr); (* eben.. *)
  2558.     VDIUtil.SetTreeColor (infoAdr, textCol, backCol);
  2559.     MagicAES.ObjcDraw(infoAdr, 0, 8, clip);
  2560.   END
  2561. END draw;
  2562.  
  2563. (*--- Allg. Verwaltung ----------------------*)
  2564.  
  2565. PROCEDURE grinInit():BOOLEAN;
  2566. (* Einiges Initialisieren, gemeckert wird selbst *)
  2567. VAR err : BOOLEAN;
  2568. BEGIN
  2569.   IF ~handlePool.InitPool() THEN
  2570.     MTE.noMemAlert();
  2571.     RETURN FALSE
  2572.   END;
  2573.   InitRsc();
  2574.   ConfVars.GetConfDefBool(cSuppressRef, RefIdUnterdruecken, FALSE);
  2575.   ConfVars.GetConfDefBool (cPersRestricted, restrictedMoves, TRUE);
  2576.   ConfVars.GetConfDefBool (cSpacePaging, spacePaging, FALSE);
  2577.   ConfVars.GetConfDefBool (cAutoNextGroup, autoNextGroup, FALSE);
  2578.   ConfVars.GetConfDefBool (cAutoNextPing, autoNextPing, FALSE);
  2579.   RETURN TRUE
  2580. END grinInit;
  2581.  
  2582. (* --- Neuzeichnen beim Baum-durchlaufen --- *)
  2583. PROCEDURE flagupdate(nr : CARDINAL; newflags : BITSET);
  2584. (* Wird an data bergeben, um die ge„nderten Flags beim Baum-durchlaufen neu zu zeichnen *)
  2585.  
  2586.   (*$Z-*)
  2587.   PROCEDURE scanWinCond(e, i : ADDRESS):BOOLEAN;
  2588.   (* Abbruchprozedur, wie in <Lists> gefordert *)
  2589.   VAR p : oneWindowPtr; clip : ARRAY[0..3] OF INTEGER;
  2590.   BEGIN
  2591.     IF e # NIL THEN
  2592.       p := e;
  2593.       IF p^.mess.MailNr = nr THEN
  2594.         p^.mess.StatusBits := newflags;
  2595.         SetNShowNewStates(p);
  2596.       END;
  2597.     END;
  2598.     RETURN FALSE
  2599.   END scanWinCond;
  2600.   (*$Z=*)
  2601.  
  2602. BEGIN
  2603.   Lists.ResetList(windows);
  2604.   Lists.ScanEntries(windows, Lists.forward, scanWinCond, NIL, v.bool);
  2605. END flagupdate;
  2606.  
  2607. (* --- Žnderungen der Flags beim Durchlaufen eines Baumes --- *)
  2608. PROCEDURE flagdelete(old : BITSET):BITSET;
  2609. (* Gel”scht-Flag setzen *)
  2610. BEGIN
  2611.   RETURN old + {dataSys.bTotalloeschung};
  2612. END flagdelete;
  2613.  
  2614. PROCEDURE flagundelete(old : BITSET):BITSET;
  2615. (* Gel”scht-Flag l”schen *)
  2616. BEGIN
  2617.   RETURN old - {dataSys.bTotalloeschung};
  2618. END flagundelete;
  2619.  
  2620. (*--- Keyboard-Events --- *)
  2621. PROCEDURE grinKey(win    : INTEGER; VAR scan, c :  CHAR;
  2622.                   VAR kstate : BITSET; VAR moreChars : BOOLEAN):BOOLEAN;
  2623. (* Keyboard-Events behandeln, wird vom Editor aufgerufen *)
  2624. VAR ptr       : oneWindowPtr; 
  2625.     newWindow        : BOOLEAN; (* "NewWindow" *)
  2626.     withAlt   : BOOLEAN; 
  2627.     withShift : BOOLEAN; 
  2628.     newCh     : CHAR;
  2629.     res       : INTEGER;
  2630.     gName     : CatTypes.String255;
  2631.     tmpName   : CatTypes.String255;
  2632.     pageW,
  2633.     pageH     : LONGINT;
  2634.     doc       : GrafBase.LongRect;
  2635.     done      : BOOLEAN;
  2636.     doInvert  : BOOLEAN;
  2637.     flag      : INTEGER;
  2638.     dir       : dirType;
  2639.     needRedraw: BOOLEAN;
  2640.     varName   : CatTypes.String255;
  2641.     num       : INTEGER;    (* Fensternummer *)
  2642.     iFont,
  2643.     iFontSize : INTEGER;
  2644.     tmpChar   : CHAR;
  2645.     
  2646. BEGIN
  2647.   (* Neue Routine, vernnftig sortiert nach Funktionsgruppen 
  2648.    *)
  2649.   moreChars := FALSE;
  2650.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) THEN
  2651.     IF (CatGlobal.WithCtrl (kstate)) OR
  2652.        (CatGlobal.WithAlt (kstate) & (c = 0C))
  2653.     THEN
  2654.       (* Jetzt Tastencodes richtig holen, das AES erz„hlt da nur Mll *)
  2655.       newCh := mtUtils.CharCode (INTEGER(ORD(scan)), kstate);
  2656.     ELSE
  2657.       newCh := c;
  2658.     END;
  2659.     newCh   := CAP(newCh);
  2660.  
  2661.     (* Sondertasten abfragen *)
  2662.     newWindow := CatGlobal.WithCtrl (kstate);
  2663.     withAlt := CatGlobal.WithAlt (kstate);
  2664.     withShift := CatGlobal.WithShift (kstate);
  2665.     
  2666.     (* Abfrage ber Scancode *)
  2667.     WITH ptr^ DO
  2668.       IF withAlt 
  2669.       THEN
  2670.         doInvert := TRUE;
  2671.         CASE newCh OF
  2672.           'L'   : flag := dataSys.bGelesen; |
  2673.           'F'   : flag := dataSys.bFiltered; |
  2674.           'I'   : flag := dataSys.bInteressant; |
  2675.           'T'   : flag := dataSys.bTeilloeschung; |
  2676.           'D'   : flag := dataSys.bTotalloeschung; |
  2677.           'K'   : flag := dataSys.bKommentieren; |
  2678.           'B'   : flag := dataSys.bAntworten; |
  2679.           'C'   : flag := dataSys.bUser1; |
  2680.           'X'   : flag := dataSys.bUser2; |
  2681.           'V'   : flag := dataSys.bVererben; |
  2682.         ELSE
  2683.           doInvert := FALSE;
  2684.         END;
  2685.         IF doInvert
  2686.         THEN
  2687.           InternalInvert (ptr, flag);
  2688.           RETURN TRUE;
  2689.         END;
  2690.         IF (scan # spaceScan)
  2691.          & (scan # pointScan)
  2692.         THEN
  2693.           (* Andere Tasten mit Alt werden hier nicht mehr behandelt
  2694.            *)
  2695.           RETURN FALSE
  2696.         END;
  2697.       END; (* IF withAlt *)
  2698.       
  2699.       done := TRUE;
  2700.       CASE scan OF
  2701.         escScan     : IF ~withShift
  2702.                       THEN 
  2703.                         msgList.listOpen (mess.Gruppe, mess.MailNr, win, mode); 
  2704.                       ELSE 
  2705.                         msgList.listOpen (mess.Gruppe, mess.MailNr, win, mOther); 
  2706.                       END 
  2707.                       |
  2708.         undoScan    : IF ptr^.undoGroup = ptr^.mess.Gruppe 
  2709.                       THEN
  2710.                         SwitchTo(ptr, ptr^.undoPos, dJump, TRUE);
  2711.                       ELSE
  2712.                         IF ~isInSearch
  2713.                         THEN
  2714.                           SwitchToNewGroup(ptr^.undoGroup, ptr^.undoPos, ptr);
  2715.                         ELSE
  2716.                           CatGlobal.Bing (0);
  2717.                         END;
  2718.                       END; |
  2719.         backspaceScan: 
  2720.                       IF CatEdit.BlockIsMarked (win) 
  2721.                       THEN
  2722.                         CatEdit.ClearBlock (win);
  2723.                       END; |
  2724.         tabScan:      msgList.listRemoveTree (listHdl, win, mess.MailNr, withShift); |
  2725.         insertScan:   (* Neuen Namen in Adressenliste eintragen *)
  2726.                       IF ptr^.mess.EigeneNachricht
  2727.                       THEN
  2728.                         MagicStrings.Assign (ptr^.mess.Empfaenger^, tmpName);
  2729.                         res := mtAlerts.Alert (1, MTE.saveName2);
  2730.                       ELSE
  2731.                         MagicStrings.Assign (ptr^.mess.Absender^, tmpName);
  2732.                         res := mtAlerts.Alert (1, MTE.saveName);
  2733.                       END;
  2734.                       IF res = 1
  2735.                       THEN
  2736.                         ListHelp.NewNameEntry (tmpName, '');
  2737.                         IF ConfVars.GetConfigBool (cSortNames, v.bool) & v.bool
  2738.                         THEN
  2739.                           data.SortList (data.names);
  2740.                         END;
  2741.                       END; |
  2742.         fiveScan,
  2743.         nullScan:     SwitchTo(ptr, lastPos, dReturn, FALSE);
  2744.       ELSE
  2745.         done := FALSE;
  2746.       END;
  2747.       IF done THEN RETURN TRUE END;
  2748.       done := TRUE;
  2749.       CASE scan OF
  2750.         pointScan,
  2751.         spaceScan   : (* Space *)
  2752.                       IF spacePaging & (kstate = {})
  2753.                       THEN
  2754.                         (* eventuell pagen *)
  2755.                         WdwManager.GetWdwDocument (win, doc);
  2756.                         WdwManager.GetScrollParms (win, pageW, pageH, v.lint, v.lint);
  2757.                         IF doc.y < doc.h - pageH
  2758.                         THEN
  2759.                           WdwManager.PageDown (win);
  2760.                           RETURN TRUE;
  2761.                         END;
  2762.                       END;
  2763.                       (* Jetzt evtl. zur n„chsten oder vorigen Nachricht *)
  2764.                       IF NextPrevPrivate (ptr, scan, newCh, kstate)
  2765.                       THEN
  2766.                         RETURN TRUE;
  2767.                       END;
  2768.                       (* Wenn wir immer noch hier sind, dann k”nnen wir einfach
  2769.                        * zur n„chsten oder vorherigen Nachricht gehen
  2770.                        *)
  2771.                       IF withAlt 
  2772.                       THEN
  2773.                         dir := dPrevMess;
  2774.                       ELSE
  2775.                         dir := dNextMess;
  2776.                       END; |
  2777.         oneScan:      dir := dPrevMess; |
  2778.         twoScan:      dir := dDownMess; |
  2779.         threeScan:    dir := dNextMess; |
  2780.         eightScan:    dir := dUpMess;   |
  2781.         fourScan:     dir := dLeftMess; |
  2782.         sixScan:      dir := dRightMess;|
  2783.       ELSE
  2784.         done := FALSE;
  2785.       END;
  2786.       IF done
  2787.       THEN
  2788.         switch (ptr, dir, newWindow, withShift);
  2789.         RETURN TRUE;
  2790.       END;
  2791.       
  2792.       (* Scancode-Auswertung abgeschlossen, jetzt nur noch normale Tasten 
  2793.        * Erstmal normale Bewegung 
  2794.        *)
  2795.       done := TRUE;
  2796.       CASE newCh OF
  2797.         '+' :   dir := dDownMess;   |
  2798.         '-' :   dir := dUpMess;     |
  2799.         '<' :   dir := dLeftMess;   |
  2800.         '>' :   dir := dRightMess;  |
  2801.         'Z' :   
  2802.                 IF (handle^.group = dataSys.private) & 
  2803.                    (~mess.EigeneNachricht)
  2804.                 THEN
  2805.                   v.bool := CheckPersonal (ptr, newCh, kstate, v.bool);
  2806.                   dir := dNextMess;
  2807.                 ELSE
  2808.                   done := FALSE;
  2809.                 END; |
  2810.         'N' :   IF NextPrevPrivate (ptr, scan, newCh, kstate)
  2811.                 THEN
  2812.                   RETURN TRUE;
  2813.                 END;
  2814.                 dir := dNextMess;   |
  2815.         'L' :   IF NextPrevPrivate (ptr, scan, newCh, kstate)
  2816.                 THEN
  2817.                   RETURN TRUE;
  2818.                 END;
  2819.                 dir := dPrevMess;   |
  2820.       ELSE
  2821.         done := FALSE;
  2822.       END;
  2823.       IF done
  2824.       THEN
  2825.         switch (ptr, dir, newWindow, withShift);
  2826.         RETURN TRUE;
  2827.       END;
  2828.  
  2829.       
  2830.       (* Jetzt kommen nur noch normale Funktionen, also auch nix mit Ctrl! *)
  2831.       IF newWindow THEN RETURN FALSE; END;
  2832.  
  2833.       (* Jetzt die brigen Funktionen *)
  2834.       done := TRUE;
  2835.       CASE newCh OF
  2836.         '0' :   SwitchTo(ptr, lastPos, dReturn, FALSE); |
  2837.         'T' :   treeList.treeOpen (ptr^.mess.Gruppe, ptr^.mess.MailNr, win); |
  2838.         'G' :   grinTools.Handle(ptr^.win, grinTools.otherGroup); |
  2839.         'U' :   (* Userinfo *)
  2840.                 ActualName (ptr^.win, tmpName);
  2841.                 IF withShift
  2842.                 THEN
  2843.                   WriteToClip (tmpName);
  2844.                 ELSE
  2845.                   Protokoll.SendHelp (tmpName);
  2846.                 END; |
  2847.         'I' :   (* Info umschalten *) 
  2848.                 IF ptr^.viewHeader = vhNone
  2849.                 THEN
  2850.                   ptr^.viewHeader := vhFull;
  2851.                 ELSE
  2852.                   ptr^.viewHeader := vhNone;
  2853.                 END;
  2854.                 SwitchTo (ptr, ptr^.mess.MailNr, dNone, FALSE); |
  2855.         'Q' :   CatEdit.MarkMultiple (win); |
  2856.         'R' :   WITH ptr^.mess DO
  2857.                   GroupSelect.GroupName (Gruppe, gName);
  2858.                   IF EigeneNachricht & (Gruppe = dataSys.private)
  2859.                   THEN
  2860.                     MagicStrings.Assign (Empfaenger^, tmpName);
  2861.                   ELSE
  2862.                     MagicStrings.Assign (Absender^, tmpName);
  2863.                   END;
  2864.                   WiederVorlage.AddResub (gName, MailID^, tmpName, Betreff^, tauschDate);
  2865.                   IF  (ptr^.handle^.group = dataSys.private) & 
  2866.                       (~EigeneNachricht) 
  2867.                   THEN
  2868.                     IF ConfVars.GetConfigBool (cPostponeResubs, v.bool) & v.bool
  2869.                      & (Status = 'N')
  2870.                     THEN
  2871.                       tmpChar := 'Z';
  2872.                       v.bool := CheckPersonal (ptr, tmpChar, {}, v.bool);
  2873.                     END;
  2874.                   END;
  2875.                 END; |
  2876.         'C' :   (* Nachricht kopieren *)
  2877.                 IF ptr^.handle^.group = dataSys.private
  2878.                 THEN 
  2879.                   grinTools.Handle(ptr^.win, grinTools.copy) 
  2880.                 END; |
  2881.         'K' :   IF ptr^.handle^.group = dataSys.private
  2882.                 THEN 
  2883.                   IF ptr^.mess.EigeneNachricht THEN
  2884.                     MTE.info(MTE.noOwnCom);
  2885.                   ELSE
  2886.                     grinTools.Handle(ptr^.win, grinTools.answer);
  2887.                   END;
  2888.                 ELSE 
  2889.                   grinTools.Handle(ptr^.win, grinTools.comment) 
  2890.                 END; |
  2891.         'B',
  2892.         'P' :   IF ptr^.mess.EigeneNachricht THEN
  2893.                   MTE.info(MTE.noOwnCom);
  2894.                 ELSE
  2895.                   grinTools.Handle(ptr^.win, grinTools.answer);
  2896.                 END; |
  2897.         'X' :   v.int := mtAlerts.Alert (1, MTE.killMsg);
  2898.                 IF v.int = 1
  2899.                 THEN
  2900.                   SendState(ptr^.mess.MailID^, 'X');
  2901.                 END; |
  2902.         'E' :   CatEdit.ToggleMode (win, CatEdit.effMode);
  2903.                 (* Get font *)
  2904.                 needRedraw := FALSE;
  2905.                 IF CatEdit.GetMode (win, CatEdit.effMode)
  2906.                 THEN
  2907.                   (* Mit Effekten, normaler Font *)
  2908.                   num := BinOps.HigherInt (number-1, 0);
  2909.                   Strings.Concat (cMsgFont, StrConv.IntToStr (num, 0), varName,   v.bool);
  2910.                   ConfVars.GetConfDefInt (varName, iFont, 1);
  2911.                   Strings.Concat (cMsgSize, StrConv.IntToStr (num, 0), varName, v.bool);
  2912.                   ConfVars.GetConfDefInt (varName, iFontSize, 10);
  2913.                   CatEdit.SelectEditFont (win, iFont, iFontSize);
  2914.                 ELSE
  2915.                   (* Ohne Effekte, Tabellenfont *)
  2916.                   ConfVars.GetConfDefInt (cMsgAltFont, iFont, 1);
  2917.                   ConfVars.GetConfDefInt (cMsgAltSize, iFontSize, 10);
  2918.                   CatEdit.SelectEditFont (win, iFont, iFontSize);
  2919.                 END;
  2920.                 IF needRedraw
  2921.                 THEN
  2922.                   WdwManager.FullRedrawWdw (win); 
  2923.                 END; |
  2924.         'W' :   IF (ptr^.handle^.group = dataSys.private) THEN 
  2925.                   grinTools.Handle(ptr^.win, grinTools.pass);
  2926.                 END;
  2927.       ELSE
  2928.         done := FALSE;
  2929.       END;
  2930.       RETURN done;
  2931.     END; (* WITH ptr^ DO *)
  2932.   ELSE
  2933.     RETURN FALSE
  2934.   END;
  2935. END grinKey;
  2936.  
  2937. (*--- Userprozeduren --------------------------*)
  2938. PROCEDURE CloseGrinWin(w : INTEGER):BOOLEAN; FORWARD;
  2939.  
  2940. PROCEDURE FindNum () : INTEGER;
  2941.   VAR i : INTEGER;
  2942. BEGIN 
  2943.   IF (globalNumber >= 0) & 
  2944.      ~ (globalNumber IN grinNums)
  2945.   THEN
  2946.     INCL (grinNums, globalNumber);
  2947.     i := globalNumber;
  2948.     globalNumber := -1;
  2949.     RETURN i
  2950.   END;
  2951.   FOR i := 0 TO 255 DO
  2952.     IF ~(i IN grinNums) THEN INCL (grinNums, i); RETURN i; END;
  2953.   END;
  2954. END FindNum;
  2955.  
  2956. PROCEDURE ClearNum (num : INTEGER);
  2957. BEGIN
  2958.   EXCL (grinNums, num);
  2959. END ClearNum;
  2960.  
  2961. (*TYPE getNumberProc = PROCEDURE ((* dataHandle *) ADDRESS):CARDINAL;*)
  2962. PROCEDURE grinOpenMessage(gruppe, which : CARDINAL;
  2963.                           nextMess: grinNextMessProc; listHandle: LONGCARD;
  2964.                           mode : openMode): INTEGER;
  2965. (* Ein Messagefenster der <gruppe> mit der Msg-nr. <which> ”ffnen *)
  2966.   PROCEDURE Standard(ptr : data.OneGroupHandle):CARDINAL;
  2967.   BEGIN
  2968.     RETURN which
  2969.   END Standard;
  2970. BEGIN
  2971.   RETURN grinOpenWithProc(gruppe, Standard, nextMess, listHandle, mode);
  2972. END grinOpenMessage;
  2973.  
  2974. (*$H+*)
  2975. PROCEDURE grinOpenWithProc(gruppe : CARDINAL; whichNumber : getNumberProc;
  2976.                           nextMess: grinNextMessProc; listHandle : LONGCARD;
  2977.                           mode    : openMode): INTEGER;
  2978. (* Ein Messagefenster der gruppe <gruppe> an der Stelle ”ffnen, die von *)
  2979. (* der bergebenen Prozedur zurckgeliefert wird                        *)
  2980. (*$H= *)
  2981. VAR messPtr   : oneWindowPtr;
  2982.     handlePtr : handlePool.oneHandlePtr;
  2983.     work      : GrafBase.Rectangle;
  2984.     varName   : CatTypes.String255;
  2985.     num       : INTEGER;
  2986.     wdw       : INTEGER;
  2987.     vhMode    : INTEGER;
  2988. BEGIN
  2989.   IF handlePool.BlankToList(messPtr, TSIZE(oneWindow), windows) THEN
  2990.     IF handlePool.GetOneDatahandle(gruppe, handlePtr) THEN
  2991.       messPtr^.handle     := handlePtr;
  2992.       messPtr^.nextMsg    := nextMess;
  2993.       messPtr^.listHdl    := listHandle;
  2994.       messPtr^.lastLine   := headerNone;
  2995.       messPtr^.mode       := mode;
  2996.       messPtr^.readchange := FALSE;
  2997.       messPtr^.treeMode   := FALSE;
  2998.       messPtr^.isLocked   := FALSE;
  2999.       messPtr^.inEvent    := FALSE;
  3000.       ConfVars.GetConfDefInt (cViewHeaderMode, vhMode, 0);
  3001.       CASE vhMode OF
  3002.         0 : messPtr^.viewHeader := vhNone; |
  3003.         1 : messPtr^.viewHeader := vhFull;
  3004.       ELSE
  3005.       END;
  3006.       IF GetOneMessage(messPtr, whichNumber(handlePtr^.Zugriff)) THEN (* Nachricht lesen *)
  3007.         MakeTitle(messPtr);
  3008.         WITH messPtr^ DO
  3009.           win := -1;
  3010.           inObjcDraw := FALSE;
  3011.           (* Ein paar neue Zeilen *)
  3012.           number := FindNum ();
  3013.           Strings.Concat (cMsgWindow, StrConv.IntToStr (number, 0), varName,
  3014.                           v.bool);
  3015.           IF ~ConfVars.GetConfigRect (varName, work)
  3016.           THEN
  3017.             num := BinOps.HigherInt (number-1, 0);
  3018.             Strings.Concat (cMsgWindow, StrConv.IntToStr (num, 0), varName, v.bool);
  3019.             ConfVars.GetConfDefRect (varName, work, EditTypes.deskSize);
  3020.             IF ~RectFuncs.RectEqual (work, EditTypes.deskSize)
  3021.             THEN
  3022.               INC (work.x, 2*mtAppl.CharWidth);
  3023.               INC (work.y, mtAppl.CharHeight);
  3024.             END;
  3025.             Strings.Concat (cMsgFont, StrConv.IntToStr (num, 0), varName,   v.bool);
  3026.             ConfVars.GetConfDefInt (varName, font, 1);
  3027.             Strings.Concat (cMsgSize, StrConv.IntToStr (num, 0), varName, v.bool);
  3028.             ConfVars.GetConfDefInt (varName, fontSize, 10);
  3029.             (* Und jetzt direkt wieder setzen *)
  3030.             Strings.Concat (cMsgWindow, StrConv.IntToStr (number, 0), varName, v.bool);
  3031.             v.bool := ConfVars.SetConfigRect (varName, work);
  3032.             Strings.Concat (cMsgFont, StrConv.IntToStr (number, 0), varName, v.bool);
  3033.             v.bool := ConfVars.SetConfigInt (varName, font);
  3034.             Strings.Concat (cMsgSize, StrConv.IntToStr (number, 0), varName, v.bool);
  3035.             v.bool := ConfVars.SetConfigInt (varName, fontSize);
  3036.           ELSE
  3037.             Strings.Concat (cMsgFont, StrConv.IntToStr (number, 0), varName,   v.bool);
  3038.             ConfVars.GetConfDefInt (varName, font, 1);
  3039.             Strings.Concat (cMsgSize, StrConv.IntToStr (number, 0), varName, v.bool);
  3040.             ConfVars.GetConfDefInt (varName, fontSize, 10);
  3041.           END;
  3042.           globalNumber := number;
  3043.  
  3044.           IF CatEdit.OpenEditBuffer(title, info, FALSE, 
  3045.                                     viewBuff, viewLen,
  3046.                                     (* mess.Text, LONG(mess.textLen), *)
  3047.                                     viewAllocated, (* ~refSuppressed, *)
  3048.                                     isEnriched,
  3049.                                     font, fontSize, work,
  3050.                                     TRUE,
  3051.                                     ADDRESS(click), ADDRESS(getRect),
  3052.                                     ADDRESS(draw), ADDRESS(CloseGrinWin),
  3053.                                     ADDRESS(grinKey), ADDRESS(grinTop), ADDRESS(grinUntop), 
  3054.                                     ADDRESS (grinGetHeaderInfo),
  3055.                                     win)
  3056.                               (* dorthin kommt das Fensterhandle im Erfolgsfall *)
  3057.          THEN
  3058.            (* DD-Server anmelden *)
  3059.            CatEdit.InstallUserDD (win, grinDDGetMaxExts,
  3060.                                        grinDDGetExt,
  3061.                                        grinDDGetExtName,
  3062.                                        grinDDGetSize,
  3063.                                        grinDDGetData);
  3064.            (* jetzt im Editor, doppelt wg. Struktur *)
  3065.            VDIStandards.StatusEnable (TRUE);
  3066.            wdw := win;
  3067.            (* Wenn refSuppressed TRUE ist, dann mssen wir hier den Speicher 
  3068.             * freigeben
  3069.             *)
  3070.            IF refSuppressed & (originalText # NIL)
  3071.            THEN
  3072.              DEALLOCATE(originalText, 0); 
  3073.              refSuppressed := FALSE;
  3074.            ELSE
  3075.              IF viewAllocated
  3076.              THEN
  3077.                DEALLOCATE (mess.Text, 0);
  3078.              END;
  3079.            END;
  3080.            Protokoll.SendNewMsgInWdw();
  3081.            IF (dataSys.bComToOwnMessage IN mess.StatusBits) OR
  3082.               (dataSys.bOldComToOwnMessage IN mess.StatusBits) 
  3083.            (*
  3084.            OR (dataSys.bOwnMessage      IN mess.StatusBits) 
  3085.            *)
  3086.            THEN
  3087.               CatGlobal.Bing (0);
  3088.            END;
  3089.          ELSE
  3090.            IF refSuppressed & (originalText # NIL)
  3091.            THEN
  3092.              DEALLOCATE(originalText, 0); 
  3093.              refSuppressed := FALSE;
  3094.            ELSE
  3095.              IF viewAllocated
  3096.              THEN 
  3097.                DEALLOCATE(mess.Text, 0); 
  3098.              END;
  3099.            END;
  3100.            (* vorher: 
  3101.            DEALLOCATE(mess.Text, LONG(mess.textLen));
  3102.            *)
  3103.            ClearNum (number);                              (* <=== NEU! *)
  3104.            msgList.listUnlockWdw (listHdl);
  3105.            handlePool.FreeOneDataHandle(handlePtr);
  3106.            handlePool.FreeOnePtr(messPtr, windows);
  3107.            wdw := -1;
  3108.          END;
  3109.          globalNumber := -1;
  3110.          lastPos := mess.MailNr;
  3111.          undoPos := mess.MailNr;
  3112.          undoGroup := gruppe;
  3113.          undoTreeRoot := mess.MailNr;
  3114.          data.SetLastReadMsg(handle^.group, mess.MailNr);
  3115.          RETURN wdw;
  3116.         END;
  3117.       ELSE
  3118.         msgList.listUnlockWdw (messPtr^.listHdl);
  3119.         handlePool.FreeOneDataHandle(handlePtr);
  3120.         handlePool.FreeOnePtr(messPtr, windows);
  3121.         (* Wer macht die Fehlermeldung..? *)
  3122.         MTE.info(MTE.noFound); (* ich *)
  3123.       END;
  3124.     ELSE
  3125.       msgList.listUnlockWdw (messPtr^.listHdl);
  3126.       handlePool.FreeOnePtr(messPtr, windows);
  3127.       MTE.noMemAlert();
  3128.     END;
  3129.   ELSE
  3130.     MTE.noMemAlert();
  3131.   END;
  3132.   RETURN -1;
  3133. END grinOpenWithProc;
  3134.  
  3135. (* grinOpenHeader fehlt noch, kommt, sobald das Grundgerst steht *)
  3136.  
  3137. PROCEDURE ClosePtr(p : oneWindowPtr);
  3138.   VAR varName : CatTypes.String255;
  3139.       full    : GrafBase.Rectangle;
  3140. BEGIN
  3141.   setReadFlag(p);
  3142.   WITH p^ DO
  3143.     Strings.Concat (cMsgWindow, StrConv.IntToStr (number, 0), varName, v.bool);
  3144.     WdwManager.GetWdwSize  (win, full); (* Gr”že des Fensters abfragen *)
  3145.     v.bool := ConfVars.SetConfigRect (varName, full);
  3146.     Strings.Concat (cMsgFont, StrConv.IntToStr (number, 0), varName, v.bool);
  3147.     v.bool := ConfVars.SetConfigInt (varName, font);
  3148.     Strings.Concat (cMsgSize, StrConv.IntToStr (number, 0), varName, v.bool);
  3149.     v.bool := ConfVars.SetConfigInt (varName, fontSize);
  3150.     ClearNum (number);
  3151.   END;
  3152.   msgList.listUnlockWdw (p^.listHdl);
  3153.   handlePool.FreeOneDataHandle(p^.handle);
  3154.   DEALLOCATE(p^.mess.InfoStrings, 0);
  3155.   IF p^.treeMode THEN DEALLOCATE(p^.stack, 0); END;
  3156.   handlePool.FreeOnePtr(p, windows);
  3157. END ClosePtr;
  3158.  
  3159. (*$Z+*)
  3160. PROCEDURE CloseGrinWin(win : INTEGER): BOOLEAN;
  3161. (*$Z=*)
  3162. VAR p : oneWindowPtr;
  3163. BEGIN
  3164.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, p) THEN
  3165.     IF p^.isLocked
  3166.     THEN 
  3167.       (* Suche l„uft, nicht schliežen! *)
  3168.       RETURN FALSE
  3169.     END;
  3170.     ClosePtr(p)
  3171.   END;
  3172.   RETURN TRUE;
  3173. END CloseGrinWin;
  3174.  
  3175. PROCEDURE grinClose(win : INTEGER);                             (* exportet *)
  3176. VAR p : oneWindowPtr;
  3177. BEGIN
  3178.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, p) THEN
  3179.     CatEdit.CloseEditBuffer(win)
  3180.   END;
  3181. END grinClose;
  3182.  
  3183. PROCEDURE GetWdwFont (wdw: INTEGER; VAR iFont, iFontSize : INTEGER);
  3184. (* Holt den eingestellten Font *)
  3185. VAR p : oneWindowPtr;
  3186.     varName : CatTypes.String255;
  3187. BEGIN
  3188.   IF handlePool.FindEntry(ADR(wdw), FindWinCond, windows, p) THEN
  3189.     WITH p^ DO
  3190.       Strings.Concat (cMsgFont, StrConv.IntToStr (number, 0), varName, v.bool);
  3191.       ConfVars.GetConfDefInt (varName, iFont, 1);
  3192.       Strings.Concat (cMsgSize, StrConv.IntToStr (number, 0), varName, v.bool);
  3193.       ConfVars.GetConfDefInt (varName, iFontSize, 10);
  3194.     END;
  3195.   END;
  3196. END GetWdwFont;
  3197.  
  3198. PROCEDURE GetAlternativeFont (VAR font, fontSize : INTEGER);
  3199. (* Holt den alternativen Font *)
  3200. BEGIN
  3201.   ConfVars.GetConfDefInt (cMsgAltFont, font, 1);
  3202.   ConfVars.GetConfDefInt (cMsgAltSize, fontSize, 10);
  3203. END GetAlternativeFont;
  3204.  
  3205. PROCEDURE grinWithEffects (win: INTEGER): BOOLEAN;
  3206. (* Gibt zurck, ob momentan Effekte angezeigt werden oder nicht
  3207.  *)
  3208. VAR p : oneWindowPtr;
  3209.     varName : CatTypes.String255;
  3210. BEGIN
  3211.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, p) THEN
  3212.     RETURN CatEdit.GetMode (win, CatEdit.effMode);
  3213.   END;
  3214.   RETURN FALSE;
  3215. END grinWithEffects;
  3216.  
  3217. PROCEDURE grinSetAlternativeFont (win, iFont, iFontSize : INTEGER);
  3218. (* Setzt den Font fr das Anzeigefenster *)
  3219. VAR p : oneWindowPtr;
  3220.     varName : CatTypes.String255;
  3221. BEGIN
  3222.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, p) THEN
  3223.     (* p^.font := font; *)
  3224.     (* p^.fontSize := fontSize; *)
  3225.     WITH p^ DO
  3226.       v.bool := ConfVars.SetConfigInt (cMsgAltFont, iFont);
  3227.       v.bool := ConfVars.SetConfigInt (cMsgAltSize, iFontSize);
  3228.     END;
  3229.     IF ~CatEdit.GetMode (win, CatEdit.effMode)
  3230.     THEN
  3231.       CatEdit.SelectEditFont (win, iFont, iFontSize);
  3232.     END;
  3233.   END;
  3234. END grinSetAlternativeFont;
  3235.  
  3236. PROCEDURE grinSetFont (win, iFont, iFontSize : INTEGER);
  3237. (* Setzt den Font fr das Anzeigefenster *)
  3238. VAR p : oneWindowPtr;
  3239.     varName : CatTypes.String255;
  3240. BEGIN
  3241.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, p) THEN
  3242.     p^.font := iFont;
  3243.     p^.fontSize := iFontSize;
  3244.     WITH p^ DO
  3245.       Strings.Concat (cMsgFont, StrConv.IntToStr (number, 0), varName, v.bool);
  3246.       v.bool := ConfVars.SetConfigInt (varName, font);
  3247.       Strings.Concat (cMsgSize, StrConv.IntToStr (number, 0), varName, v.bool);
  3248.       v.bool := ConfVars.SetConfigInt (varName, fontSize);
  3249.     END;
  3250.     IF CatEdit.GetMode (win, CatEdit.effMode)
  3251.     THEN
  3252.       CatEdit.SelectEditFont (win, iFont, iFontSize);
  3253.     END;
  3254.   END;
  3255. END grinSetFont;
  3256.  
  3257. PROCEDURE grinSavePos();
  3258. (* Sichert die Positionen aller grin-Fenster *)
  3259. VAR lauf : oneWindowPtr;
  3260.     varName : ARRAY [0..255] OF CHAR;
  3261.     full    : GrafBase.Rectangle;
  3262. BEGIN
  3263.   Lists.ResetList(windows);
  3264.   lauf := Lists.NextEntry(windows);
  3265.   WHILE lauf # NIL DO
  3266.     WITH lauf^ DO
  3267.       Strings.Concat (cMsgGroup, StrConv.IntToStr (number, 0), varName, v.bool);
  3268.       v.bool := ConfVars.SetConfigLongInt (varName, VAL(LONGINT, mess.Gruppe));
  3269.       Strings.Concat (cMsgMessage, StrConv.IntToStr (number, 0), varName, v.bool);
  3270.       v.bool := ConfVars.SetConfigLongInt (varName, VAL(LONGINT, mess.MailNr));
  3271.  
  3272.       Strings.Concat (cMsgWindow, StrConv.IntToStr (number, 0), varName, v.bool);
  3273.       WdwManager.GetWdwSize (win, full); (* Gr”že des Fensters abfragen *)
  3274.       v.bool := ConfVars.SetConfigRect (varName, full);
  3275.       Strings.Concat (cMsgFont, StrConv.IntToStr (number, 0), varName, v.bool);
  3276.       v.bool := ConfVars.SetConfigInt (varName, font);
  3277.       Strings.Concat (cMsgSize, StrConv.IntToStr (number, 0), varName, v.bool);
  3278.       v.bool := ConfVars.SetConfigInt (varName, fontSize);
  3279.     END;
  3280.     lauf := Lists.NextEntry(windows);
  3281.   END;
  3282. END grinSavePos;
  3283.  
  3284. PROCEDURE grinRestorePos();
  3285. VAR varName : ARRAY [0..255] OF CHAR;
  3286.     number  : INTEGER;
  3287.     gruppe, 
  3288.     mailNr  : CARDINAL;
  3289. BEGIN
  3290.   FOR number := 0 TO 255 DO 
  3291.     Strings.Concat (cMsgGroup, StrConv.IntToStr (number, 0), varName, v.bool);
  3292.     IF ConfVars.GetConfigLongInt (varName, v.lint) 
  3293.     THEN
  3294.       gruppe := VAL (CARDINAL, v.lint);
  3295.       Strings.Concat (cMsgMessage, StrConv.IntToStr (number, 0), varName, v.bool);
  3296.       IF ConfVars.GetConfigLongInt (varName, v.lint)
  3297.       THEN
  3298.         mailNr := VAL (CARDINAL, v.lint);
  3299.         globalNumber := number;
  3300.         v.int := grinOpenMessage (gruppe, mailNr, grinNextMess, 0, mOther);
  3301.       END;
  3302.     END;
  3303.   END;
  3304.   globalNumber := -1;
  3305. END grinRestorePos;
  3306.  
  3307. (*
  3308. PROCEDURE grinWindowEvent(pBuff : ADDRESS):BOOLEAN;
  3309. (* Diejenigen Windowevents behandeln, die vom Modul beachtet oder
  3310.  * abgefangen werden mssen; Bei TRUE wurde das event komplett behandelt.
  3311.  *)
  3312. VAR mBuff : POINTER TO ARRAY[0..7] OF INTEGER;
  3313.     p     : oneWindowPtr;
  3314. BEGIN
  3315.   mBuff := pBuff;
  3316.   IF handlePool.FindEntry(ADR(mBuff^[3]), FindWinCond, windows, p) THEN 
  3317.     IF (mBuff^[0] = MagicAES.WMSIZED) OR (mBuff^[0] = MagicAES.WMMOVED) THEN
  3318.       AdjustPosition(mBuff^[4], mBuff^[5], mBuff^[6]);
  3319.     END;
  3320.   END;
  3321.   RETURN FALSE
  3322. END grinWindowEvent;
  3323. *)
  3324.  
  3325. PROCEDURE grinCloseAll();                                       (* exportet *)
  3326. (* Alle Fenster schliežen *)
  3327. VAR lauf : oneWindowPtr;
  3328. BEGIN
  3329.   Lists.ResetList(windows);
  3330.   lauf := Lists.NextEntry(windows);
  3331.   WHILE lauf # NIL DO
  3332.     grinClose(lauf^.win);
  3333.     lauf := Lists.NextEntry(windows);
  3334.   END;
  3335. END grinCloseAll;
  3336.  
  3337. PROCEDURE grinWindowTop(win : INTEGER):BOOLEAN;                 (* exportet *)
  3338. (* Ist ein Anzeigefenster das oberste? *)
  3339. BEGIN
  3340.   RETURN handlePool.FindEntry(ADR(win), FindWinCond, windows, v.a);
  3341. END grinWindowTop;
  3342.  
  3343. (* Auskunftprozeduren *)
  3344. PROCEDURE ActualSubject(win : INTEGER; VAR subject : ARRAY OF CHAR);
  3345. VAR ptr : oneWindowPtr;
  3346. BEGIN
  3347.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) THEN
  3348.     MagicStrings.Assign(ptr^.mess.Betreff^, subject);
  3349.   ELSE
  3350.     subject[0] := 0C;
  3351.   END;
  3352. END ActualSubject;
  3353.  
  3354. PROCEDURE ActualID(win : INTEGER; VAR ID : ARRAY OF CHAR);
  3355. VAR ptr : oneWindowPtr;
  3356. BEGIN
  3357.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) THEN
  3358.     MagicStrings.Assign(ptr^.mess.MailID^, ID);
  3359.   ELSE
  3360.     ID[0] := 0C;
  3361.   END;
  3362. END ActualID;
  3363.  
  3364. PROCEDURE ActualMId(win : INTEGER; VAR ID : ARRAY OF CHAR);
  3365. VAR ptr : oneWindowPtr;
  3366. BEGIN
  3367.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) THEN
  3368.     MagicStrings.Assign(ptr^.mess.mid^, ID);
  3369.   ELSE
  3370.     ID[0] := 0C;
  3371.   END;
  3372. END ActualMId;
  3373.  
  3374. PROCEDURE ActualSender(win : INTEGER; VAR sender : ARRAY OF CHAR);
  3375. VAR ptr : oneWindowPtr;
  3376. BEGIN
  3377.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) THEN
  3378.     IF ptr^.mess.sender # NIL
  3379.     THEN
  3380.       MagicStrings.Assign (ptr^.mess.sender^, sender);
  3381.     END;
  3382.   ELSE
  3383.     sender[0] := 0C;
  3384.   END;
  3385. END ActualSender;
  3386.  
  3387. PROCEDURE ActualWdwName (win : INTEGER; VAR sender : ARRAY OF CHAR);
  3388.   VAR ptr : oneWindowPtr;
  3389. BEGIN
  3390.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) THEN
  3391.     IF (ptr^.mess.EigeneNachricht) & (ptr^.mess.Gruppe = dataSys.private)
  3392.     THEN
  3393.       MagicStrings.Assign (ptr^.mess.Empfaenger^, sender);
  3394.     ELSE
  3395.       IF ptr^.mess.name^[0] = 0C THEN
  3396.         MagicStrings.Assign (ptr^.mess.Absender^, sender);
  3397.       ELSE
  3398.         MagicStrings.Assign (ptr^.mess.name^, sender);
  3399.       END;
  3400.     END;
  3401.   ELSE
  3402.     sender[0] := 0C;
  3403.   END;
  3404. END ActualWdwName;
  3405.  
  3406. PROCEDURE ActualFrom (win : INTEGER; VAR sender : ARRAY OF CHAR);
  3407. VAR ptr : oneWindowPtr;
  3408. BEGIN
  3409.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) THEN
  3410.     MagicStrings.Assign (ptr^.mess.Absender^, sender);
  3411.   ELSE
  3412.     sender[0] := 0C;
  3413.   END;
  3414. END ActualFrom;
  3415.  
  3416. PROCEDURE ActualReplyto (win : INTEGER; VAR sender : ARRAY OF CHAR);
  3417. CONST cReplyTo = 'Reply-To:';
  3418.  
  3419. VAR ptr : oneWindowPtr;
  3420.     line: ARRAY [0..511] OF CHAR;
  3421.     lineAnf : ARRAY [0..40] OF CHAR;
  3422.     l   : CARDINAL;
  3423. BEGIN
  3424.   sender[0] := 0C;
  3425.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) THEN
  3426.     IF ptr^.mess.replyTo # NIL
  3427.     THEN
  3428.       MagicStrings.Assign(ptr^.mess.replyTo^, sender);
  3429.     END;
  3430.     IF sender[0] = 0C
  3431.     THEN
  3432.       (* Im Text nachsehen *)
  3433.       IF CatEdit.GetTextLine (ptr^.win, 0, line, v.int)
  3434.       THEN
  3435.         MagicStrings.Assign (line, lineAnf);
  3436.         lineAnf[LENGTH(cReplyTo)] := '';
  3437.         IF AssFuncs.StrIequal (cReplyTo, lineAnf)
  3438.         THEN
  3439.           MagicStrings.Delete (line, 0, LENGTH (cReplyTo));
  3440.           Strings.DelLeadingBlanks (line);
  3441.           MagicStrings.Assign (line, sender);
  3442.           (* Steuerzeichen am Ende entfernen *)
  3443.           l := LENGTH (sender);
  3444.           WHILE (l > 0) & (ORD(sender[l-1]) < ORD(' ')) DO 
  3445.             DEC (l); sender[l] := ''; 
  3446.           END;
  3447.         END;
  3448.       END;
  3449.     END;
  3450.   END;
  3451. END ActualReplyto;
  3452.  
  3453. PROCEDURE ActualName (win : INTEGER; VAR name : ARRAY OF CHAR);
  3454. VAR ptr : oneWindowPtr;
  3455. BEGIN
  3456.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) THEN
  3457.     IF (ptr^.mess.name # NIL) & (ptr^.mess.name^[0] = '')
  3458.     THEN
  3459.       MagicStrings.Assign(ptr^.mess.Absender^, name);
  3460.     ELSIF (ptr^.mess.name # NIL)
  3461.     THEN
  3462.       MagicStrings.Assign(ptr^.mess.name^, name);
  3463.     ELSE
  3464.       name[0] := 0C;
  3465.     END;
  3466.   ELSE
  3467.     name[0] := 0C;
  3468.   END;
  3469. END ActualName;
  3470.  
  3471. PROCEDURE ActualReceiver(win : INTEGER; VAR receiver : ARRAY OF CHAR);
  3472. VAR ptr : oneWindowPtr;
  3473. BEGIN
  3474.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) THEN
  3475.     IF ptr^.mess.Empfaenger # NIL
  3476.     THEN
  3477.       MagicStrings.Assign(ptr^.mess.Empfaenger^, receiver);
  3478.     ELSE
  3479.       receiver[0] := 0C;
  3480.     END;
  3481.   ELSE
  3482.     receiver[0] := 0C;
  3483.   END;
  3484. END ActualReceiver;
  3485.  
  3486. PROCEDURE ActualGroup(win : INTEGER; VAR group : ARRAY OF CHAR);
  3487. VAR ptr : oneWindowPtr;
  3488. BEGIN
  3489.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) THEN
  3490.     GroupSelect.GroupName(ptr^.handle^.group, group);
  3491.   ELSE
  3492.     group[0] := 0C;
  3493.   END;
  3494. END ActualGroup;
  3495.  
  3496. PROCEDURE ActualDist (win : INTEGER; VAR dist: data.tDistribution);
  3497. VAR ptr : oneWindowPtr;
  3498. BEGIN
  3499.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) THEN
  3500.     dist := ptr^.mess.distribution;
  3501.   ELSE
  3502.     dist := data.dNone;
  3503.   END;
  3504. END ActualDist;
  3505.  
  3506. PROCEDURE ActualGroupNr(win : INTEGER):CARDINAL;
  3507. VAR ptr : oneWindowPtr;
  3508. BEGIN
  3509.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) THEN
  3510.     RETURN ptr^.handle^.group
  3511.   ELSE
  3512.     RETURN dataSys.maxGroup+1
  3513.   END;
  3514. END ActualGroupNr;
  3515.  
  3516. PROCEDURE ActualRefId (win: INTEGER; VAR id: ARRAY OF CHAR);
  3517. VAR ptr : oneWindowPtr;
  3518. BEGIN
  3519.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) THEN
  3520.     MagicStrings.Assign (ptr^.mess.KommentierteID, id);
  3521.   ELSE
  3522.     id[0] := 0C;
  3523.   END;
  3524. END ActualRefId;
  3525.  
  3526. PROCEDURE ActualRId (win: INTEGER; VAR id: ARRAY OF CHAR);
  3527. VAR ptr : oneWindowPtr;
  3528. BEGIN
  3529.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) THEN
  3530.     IF ptr^.mess.rid # NIL
  3531.     THEN
  3532.       MagicStrings.Assign(ptr^.mess.rid^, id);
  3533.     ELSE
  3534.       id[0] := 0C;
  3535.     END;
  3536.   ELSE
  3537.     id[0] := 0C;
  3538.   END;
  3539. END ActualRId;
  3540.  
  3541. PROCEDURE ActualFollowup (win: INTEGER; VAR id: ARRAY OF CHAR);
  3542. VAR ptr : oneWindowPtr;
  3543. BEGIN
  3544.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) THEN
  3545.     IF ptr^.mess.followupTo # NIL
  3546.     THEN
  3547.       MagicStrings.Assign(ptr^.mess.followupTo^, id);
  3548.     ELSE
  3549.       id[0] := 0C;
  3550.     END;
  3551.   ELSE
  3552.     id[0] := 0C;
  3553.   END;
  3554. END ActualFollowup;
  3555.  
  3556. PROCEDURE ActualDate (win: INTEGER; VAR date: ConvertDate.Date;
  3557.                       VAR time: ConvertDate.Time);
  3558. VAR ptr : oneWindowPtr;
  3559. BEGIN
  3560.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr)
  3561.   THEN
  3562.     ConvertDate.CatDate2Datim (ptr^.mess.tauschDate, date, time);
  3563.   ELSE
  3564.     Block.Clear (ADR(date), SIZE(date));
  3565.     Block.Clear (ADR(time), SIZE(time));
  3566.   END;
  3567. END ActualDate;
  3568.  
  3569. PROCEDURE ActualStatusDate (win: INTEGER; VAR date: ConvertDate.Date;
  3570.                       VAR time: ConvertDate.Time);
  3571. VAR ptr : oneWindowPtr;
  3572. BEGIN
  3573.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) 
  3574.   THEN
  3575.     ConvertDate.CatDate2Datim (ptr^.mess.statusDate, date, time);
  3576.   ELSE
  3577.     Block.Clear (ADR(date), SIZE(date));
  3578.     Block.Clear (ADR(time), SIZE(time));
  3579.   END;
  3580. END ActualStatusDate;
  3581.  
  3582. PROCEDURE ActualIsOwn (win: INTEGER; VAR isOwn: BOOLEAN);
  3583. VAR ptr : oneWindowPtr;
  3584. BEGIN
  3585.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) 
  3586.   THEN
  3587.     isOwn := ptr^.mess.EigeneNachricht;
  3588.   ELSE
  3589.     isOwn := FALSE;
  3590.   END;
  3591. END ActualIsOwn;
  3592.  
  3593. PROCEDURE ActualText (win: INTEGER; txtBuf: ADDRESS);
  3594. VAR ptr : oneWindowPtr;
  3595. BEGIN
  3596.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) THEN
  3597.     IF ptr^.viewBuff # NIL
  3598.     THEN
  3599.       Block.Copy (ptr^.viewBuff, ptr^.viewLen, txtBuf);
  3600.     END;
  3601.   END;
  3602. END ActualText;
  3603.  
  3604. PROCEDURE ActualOrgText (win: INTEGER; txtBuf: ADDRESS);
  3605. VAR ptr : oneWindowPtr;
  3606.     tmpMess: data.MessageType;
  3607. BEGIN
  3608.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) 
  3609.   THEN
  3610.     data.ReadMessage (ptr^.handle^.Zugriff, ptr^.mess.MailNr, tmpMess);
  3611.     IF tmpMess.InfoStrings # NIL
  3612.     THEN
  3613.       DEALLOCATE (tmpMess.InfoStrings, 0);
  3614.     END;
  3615.     IF tmpMess.Text # NIL
  3616.     THEN
  3617.       Block.Copy (tmpMess.Text, tmpMess.textLen, txtBuf);
  3618.       DEALLOCATE (tmpMess.Text, 0);
  3619.     END;
  3620.   END;
  3621. END ActualOrgText;
  3622.  
  3623. PROCEDURE ActualInternalId (win: INTEGER; VAR Id: LONGCARD);
  3624. VAR ptr : oneWindowPtr;
  3625.     tmpMess: data.MessageType;
  3626. BEGIN
  3627.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) 
  3628.   THEN
  3629.     Id := LONG(ptr^.mess.Gruppe) * 65536L + LONG(ptr^.mess.MailNr);
  3630.   ELSE
  3631.     Id := 0FFFFFFFFH;
  3632.   END;
  3633. END ActualInternalId;
  3634.  
  3635. PROCEDURE ActualMime (win: INTEGER; VAR mime: ARRAY OF CHAR);
  3636. VAR ptr : oneWindowPtr;
  3637. BEGIN
  3638.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) THEN
  3639.     IF ptr^.mess.mime # NIL
  3640.     THEN
  3641.       MagicStrings.Assign(ptr^.mess.mime^, mime);
  3642.     ELSE
  3643.       mime[0] := 0C;
  3644.     END;
  3645.   ELSE
  3646.     mime[0] := 0C;
  3647.   END;
  3648. END ActualMime;
  3649.  
  3650. PROCEDURE ActualGate (win: INTEGER; VAR gate: ARRAY OF CHAR);
  3651. VAR ptr : oneWindowPtr;
  3652. BEGIN
  3653.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) THEN
  3654.     IF ptr^.mess.gate # NIL
  3655.     THEN
  3656.       MagicStrings.Assign(ptr^.mess.gate^, gate);
  3657.     ELSE
  3658.       gate[0] := 0C;
  3659.     END;
  3660.   ELSE
  3661.     gate[0] := 0C;
  3662.   END;
  3663. END ActualGate;
  3664.  
  3665. PROCEDURE ActualBox  (win: INTEGER; VAR box: ARRAY OF CHAR);
  3666. VAR ptr : oneWindowPtr;
  3667. BEGIN
  3668.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) THEN
  3669.     IF ptr^.mess.box # NIL
  3670.     THEN
  3671.       MagicStrings.Assign(ptr^.mess.box^, box);
  3672.     ELSE
  3673.       box[0] := 0C;
  3674.     END;
  3675.   ELSE
  3676.     box[0] := 0C;
  3677.   END;
  3678. END ActualBox;
  3679.  
  3680. PROCEDURE ActualStatus (win: INTEGER; VAR status: ARRAY OF CHAR);
  3681. VAR ptr : oneWindowPtr;
  3682. BEGIN
  3683.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) THEN
  3684.     MagicStrings.Assign (ptr^.mess.Status, status);
  3685.   ELSE
  3686.     status[0] := 0C;
  3687.   END;
  3688. END ActualStatus;
  3689.  
  3690. (* Gr”ženabfragen *)
  3691. PROCEDURE CheckedLength (strPtr: CatTypes.Str255Ptr): LONGCARD;
  3692. BEGIN
  3693.   IF strPtr = NIL THEN RETURN 0 END;
  3694.   RETURN LONG (LENGTH (strPtr^));
  3695. END CheckedLength;
  3696.  
  3697. PROCEDURE ActSubjectSize (win: INTEGER) : LONGCARD;
  3698. VAR ptr : oneWindowPtr;
  3699. BEGIN
  3700.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) 
  3701.   THEN
  3702.     RETURN CheckedLength (ptr^.mess.Betreff);
  3703.   END;
  3704.   RETURN 0;
  3705. END ActSubjectSize;
  3706.  
  3707. PROCEDURE ActIdSize (win: INTEGER) : LONGCARD;
  3708. VAR ptr : oneWindowPtr;
  3709. BEGIN
  3710.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) 
  3711.   THEN
  3712.     RETURN CheckedLength (ptr^.mess.MailID);
  3713.   END;
  3714.   RETURN 0;
  3715. END ActIdSize;
  3716.  
  3717. PROCEDURE ActMIdSize (win: INTEGER) : LONGCARD;
  3718. VAR ptr : oneWindowPtr;
  3719. BEGIN
  3720.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) 
  3721.   THEN
  3722.     RETURN CheckedLength (ptr^.mess.mid);
  3723.   END;
  3724.   RETURN 0;
  3725. END ActMIdSize;
  3726.  
  3727. PROCEDURE ActSenderSize (win: INTEGER) : LONGCARD;
  3728. VAR ptr : oneWindowPtr;
  3729. BEGIN
  3730.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) 
  3731.   THEN
  3732.     RETURN CheckedLength (ptr^.mess.sender);
  3733.   END;
  3734.   RETURN 0;
  3735. END ActSenderSize;
  3736.  
  3737. PROCEDURE ActFromSize (win: INTEGER) : LONGCARD;
  3738. VAR ptr : oneWindowPtr;
  3739. BEGIN
  3740.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) 
  3741.   THEN
  3742.     RETURN CheckedLength (ptr^.mess.Absender);
  3743.   END;
  3744.   RETURN 0;
  3745. END ActFromSize;
  3746.  
  3747. PROCEDURE ActReceiverSize (win: INTEGER) : LONGCARD;
  3748. VAR ptr : oneWindowPtr;
  3749. BEGIN
  3750.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) 
  3751.   THEN
  3752.     RETURN CheckedLength (ptr^.mess.Empfaenger);
  3753.   END;
  3754.   RETURN 0;
  3755. END ActReceiverSize;
  3756.  
  3757. PROCEDURE ActGroupSize (win: INTEGER) : LONGCARD;
  3758. VAR ptr : oneWindowPtr;
  3759.     name: CatTypes.String255;
  3760. BEGIN
  3761.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) 
  3762.   THEN
  3763.     GroupSelect.GroupName(ptr^.handle^.group, name);
  3764.     RETURN LONG (LENGTH (name));
  3765.   END;
  3766.   RETURN 0;
  3767. END ActGroupSize;
  3768.  
  3769. PROCEDURE ActWdwNameSize (win: INTEGER) : LONGCARD;
  3770. VAR ptr : oneWindowPtr;
  3771.     name: CatTypes.String1023;
  3772. BEGIN
  3773.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) 
  3774.   THEN
  3775.     ActualWdwName (win, name);
  3776.     RETURN LONG (LENGTH (name));
  3777.   END;
  3778.   RETURN 0;
  3779. END ActWdwNameSize;
  3780.  
  3781. PROCEDURE ActNameSize (win: INTEGER) : LONGCARD;
  3782. VAR ptr : oneWindowPtr;
  3783.     name: CatTypes.String1023;
  3784. BEGIN
  3785.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) 
  3786.   THEN
  3787.     ActualName (win, name);
  3788.     RETURN LONG (LENGTH (name));
  3789.   END;
  3790.   RETURN 0;
  3791. END ActNameSize;
  3792.  
  3793. PROCEDURE ActReplyToSize (win: INTEGER) : LONGCARD;
  3794. VAR ptr : oneWindowPtr;
  3795.     name: CatTypes.String1023;
  3796. BEGIN
  3797.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) 
  3798.   THEN
  3799.     ActualReplyto (win, name);
  3800.     RETURN LONG (LENGTH (name));
  3801.   END;
  3802.   RETURN 0;
  3803. END ActReplyToSize;
  3804.  
  3805. PROCEDURE ActRefIdSize (win: INTEGER) : LONGCARD;
  3806. VAR ptr : oneWindowPtr;
  3807. BEGIN
  3808.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) 
  3809.   THEN
  3810.     RETURN LONG (LENGTH (ptr^.mess.KommentierteID));
  3811.   END;
  3812.   RETURN 0;
  3813. END ActRefIdSize;
  3814.  
  3815. PROCEDURE ActRIdSize (win: INTEGER) : LONGCARD;
  3816. VAR ptr : oneWindowPtr;
  3817. BEGIN
  3818.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) 
  3819.   THEN
  3820.     RETURN CheckedLength (ptr^.mess.rid);
  3821.   END;
  3822.   RETURN 0;
  3823. END ActRIdSize;
  3824.  
  3825. PROCEDURE ActFollowupSize (win: INTEGER) : LONGCARD;
  3826. VAR ptr : oneWindowPtr;
  3827. BEGIN
  3828.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) 
  3829.   THEN
  3830.     RETURN CheckedLength (ptr^.mess.followupTo);
  3831.   END;
  3832.   RETURN 0;
  3833. END ActFollowupSize;
  3834.  
  3835. PROCEDURE ActDistSize (win: INTEGER) : LONGCARD;
  3836. VAR ptr : oneWindowPtr;
  3837. BEGIN
  3838.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) 
  3839.   THEN
  3840.     RETURN 2;
  3841.   END;
  3842.   RETURN 0;
  3843. END ActDistSize;
  3844.  
  3845. PROCEDURE ActStatusSize (win: INTEGER) : LONGCARD;
  3846. VAR ptr : oneWindowPtr;
  3847. BEGIN
  3848.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) 
  3849.   THEN
  3850.     RETURN 2;
  3851.   END;
  3852.   RETURN 0;
  3853. END ActStatusSize;
  3854.  
  3855. PROCEDURE ActDateSize (win: INTEGER) : LONGCARD;
  3856. VAR ptr : oneWindowPtr;
  3857. BEGIN
  3858.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) 
  3859.   THEN
  3860.     RETURN 4;
  3861.   END;
  3862.   RETURN 0;
  3863. END ActDateSize;
  3864.  
  3865. PROCEDURE ActStatusDateSize (win: INTEGER) : LONGCARD;
  3866. VAR ptr : oneWindowPtr;
  3867. BEGIN
  3868.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) 
  3869.   THEN
  3870.     RETURN 4;
  3871.   END;
  3872.   RETURN 0;
  3873. END ActStatusDateSize;
  3874.  
  3875. PROCEDURE ActTextSize (win: INTEGER) : LONGCARD;
  3876. VAR ptr : oneWindowPtr;
  3877. BEGIN
  3878.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) 
  3879.   THEN
  3880.     RETURN ptr^.viewLen;
  3881.   END;
  3882.   RETURN 0;
  3883. END ActTextSize;
  3884.  
  3885. PROCEDURE ActOrgTextSize (win: INTEGER) : LONGCARD;
  3886. VAR ptr : oneWindowPtr;
  3887.     tmpMess: data.MessageType;
  3888. BEGIN
  3889.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) 
  3890.   THEN
  3891.     data.ReadHeader (ptr^.handle^.Zugriff, ptr^.mess.MailNr, tmpMess);
  3892.     IF tmpMess.InfoStrings # NIL
  3893.     THEN 
  3894.       DEALLOCATE (tmpMess.InfoStrings, 0);
  3895.       RETURN tmpMess.textLen;
  3896.     END;
  3897.   END;
  3898.   RETURN 0;
  3899. END ActOrgTextSize;
  3900.  
  3901. PROCEDURE ActMimeSize (win: INTEGER) : LONGCARD;
  3902. VAR ptr : oneWindowPtr;
  3903. BEGIN
  3904.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) 
  3905.   THEN
  3906.     RETURN CheckedLength (ptr^.mess.mime);
  3907.   END;
  3908.   RETURN 0;
  3909. END ActMimeSize;
  3910.  
  3911. PROCEDURE ActGateSize (win: INTEGER) : LONGCARD;
  3912. VAR ptr : oneWindowPtr;
  3913. BEGIN
  3914.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) 
  3915.   THEN
  3916.     RETURN CheckedLength (ptr^.mess.gate);
  3917.   END;
  3918.   RETURN 0;
  3919. END ActGateSize;
  3920.  
  3921. PROCEDURE ActBoxSize (win: INTEGER) : LONGCARD;
  3922. VAR ptr : oneWindowPtr;
  3923. BEGIN
  3924.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) 
  3925.   THEN
  3926.     RETURN CheckedLength (ptr^.mess.box);
  3927.   END;
  3928.   RETURN 0;
  3929. END ActBoxSize;
  3930.  
  3931. PROCEDURE ActIsOwnSize (win: INTEGER) : LONGCARD;
  3932. VAR ptr : oneWindowPtr;
  3933. BEGIN
  3934.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) 
  3935.   THEN
  3936.     RETURN 2;
  3937.   END;
  3938.   RETURN 0;
  3939. END ActIsOwnSize;
  3940.  
  3941. PROCEDURE ActInternalIdSize (win: INTEGER) : LONGCARD;
  3942. VAR ptr : oneWindowPtr;
  3943. BEGIN
  3944.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) 
  3945.   THEN
  3946.     RETURN 4;
  3947.   END;
  3948.   RETURN 0;
  3949. END ActInternalIdSize;
  3950.  
  3951. PROCEDURE InvertStatus(topWin : INTEGER; whichState : CARDINAL);
  3952. (* Invertiert den angegebenen Status, entsprechende Konstanten sind in data.d zu finden *)
  3953. VAR ptr : oneWindowPtr;
  3954. BEGIN
  3955.   IF handlePool.FindEntry(ADR(topWin), FindWinCond, windows, ptr) THEN 
  3956.     InternalInvert(ptr, whichState); 
  3957.   END;
  3958. END InvertStatus;
  3959.  
  3960. PROCEDURE newStatus(topWin : INTEGER; clear, set : BITSET);
  3961. VAR ptr : oneWindowPtr;
  3962. BEGIN
  3963.   IF handlePool.FindEntry(ADR(topWin), FindWinCond, windows, ptr) THEN 
  3964.     CLEARBITS := clear; SETBITS := set;
  3965.     InternalChange(ptr, newBits); 
  3966.   END;
  3967. END newStatus;
  3968.  
  3969. PROCEDURE grinNewState(TopWin : INTEGER; newState : CHAR);
  3970. VAR ptr : oneWindowPtr;
  3971. BEGIN
  3972.   IF handlePool.FindEntry(ADR(TopWin), FindWinCond, windows, ptr) &
  3973.      (ptr^.handle^.group = dataSys.private) THEN
  3974.     changeState(ptr, newState);
  3975.   END;
  3976. END grinNewState;
  3977.  
  3978.  (* = (sUBERALL, sTEXT, sBETREFF, sTEXTnBETREFF, sABSENDER, sEMPFAENGER, sID); *)
  3979.  
  3980. PROCEDURE SearchMenu(topWin : INTEGER);
  3981. VAR res : INTEGER;
  3982. BEGIN
  3983.   res := ZSearchDial.DoSearchDial(FALSE);
  3984.   IF res = ZSearchDial.FASTAHEAD THEN
  3985.     DoSearch(topWin, TRUE);
  3986.   ELSIF res = ZSearchDial.FASTBACK THEN
  3987.     DoSearch(topWin, FALSE);
  3988.   END;
  3989. END SearchMenu;
  3990.  
  3991. PROCEDURE DoSearch(topWin : INTEGER; forward : BOOLEAN);
  3992. VAR nr   : CARDINAL;
  3993.     ptr  : oneWindowPtr;
  3994.     what : data.SearchSet;
  3995.     s    : CARDINAL;
  3996.  
  3997.     found    : BOOLEAN;
  3998.     noMore   : BOOLEAN;
  3999.     break    : BOOLEAN;
  4000.     handle   : handlePool.oneHandlePtr;
  4001.     which    : CARDINAL;
  4002.     gAnz     : CARDINAL;
  4003.     gNr      : CARDINAL;
  4004.  
  4005. BEGIN
  4006.   IF isInSearch THEN RETURN END;
  4007.   isInSearch := TRUE;
  4008.   IF suchVar.searchStr[0,0] = 0C THEN
  4009.     suchVar.searchText := FALSE;
  4010.   END;
  4011.   IF ~handlePool.FindEntry(ADR(topWin), FindWinCond, windows, ptr) OR
  4012.       ~(suchVar.searchText OR suchVar.statussearch)
  4013.   THEN
  4014.     isInSearch := FALSE;
  4015.     RETURN
  4016.   END;
  4017.   what := data.SearchSet{};
  4018.   IF suchVar.statussearch THEN INCL(what, data.inBits) END;
  4019.   IF suchVar.searchText   THEN INCL(what, data.inText) END;
  4020.   IF ~suchVar.show        THEN INCL(what, data.dontShow) END;
  4021.   IF suchVar.change       THEN INCL(what, data.changeBits) END;
  4022.   IF ~forward     THEN INCL(what, data.reverse) END;
  4023.   IF suchVar.ask          THEN INCL(what, data.ask) END;
  4024. (* ask wird noch nicht beachtet *)
  4025.  
  4026.   IF forward THEN
  4027.     s := ptr^.mess.MailNr+1; (* StartNachricht *)
  4028.   ELSE
  4029.     s := ptr^.mess.MailNr;
  4030.     IF s = 0 THEN 
  4031.      isInSearch := FALSE;
  4032.      RETURN 
  4033.     ELSE DEC(s) END;
  4034.   END;
  4035.  
  4036.   found    := FALSE;
  4037.   noMore   := FALSE;
  4038.   break    := FALSE;
  4039.   gNr      := ptr^.handle^.group;
  4040.   v.bool   := GroupSelect.GroupNumber('$&%$&%$/&/&%&/$&/Ý$/&$/&', gAnz);
  4041.   ptr^.isLocked := TRUE;
  4042.  
  4043.   WHILE ~break & (gNr # dataSys.empty) & ~found & ~stopSearch() & ~noMore DO
  4044.     IF handlePool.GetOneDatahandle(gNr, handle) THEN
  4045.       found := data.ComplexSearch(handle^.Zugriff,
  4046.                             s,                         (* StartNachricht         *)
  4047.                             suchVar.sSetBits,
  4048.                             suchVar.sClearedBits,              (* Zusammen Suchmaske     *)
  4049.                             suchVar.searchStr[0],              (* Zu suchender String    *)
  4050.                             suchVar.searchStr[1], suchVar.searchStr[2], suchVar.searchStr[3],
  4051.                             suchVar.wo[0], suchVar.wo[1], suchVar.wo[2], suchVar.wo[3],
  4052.                             suchVar.verkn[0], suchVar.verkn[1], suchVar.verkn[2],
  4053.                             suchVar.gross,                     (* grož=klein?            *)
  4054.                             suchVar.setBits,
  4055.                             suchVar.clearBits,                 (* Zusammen Setzmaske     *)
  4056.                             what,                      (* Was machen?            *)
  4057.                             break,
  4058.                             nr);
  4059.       handlePool.FreeOneDataHandle(handle);
  4060.     END;
  4061.     IF ~found & suchVar.groupsearch THEN
  4062.       IF forward THEN
  4063.         gNr := GroupSelect.NextGroupNumber(gNr);
  4064.         s   := 0;
  4065.       ELSE
  4066.         gNr := GroupSelect.PreviousGroupNumber(gNr);
  4067.         IF gNr <= dataSys.maxGroup THEN 
  4068.           s   := data.LastMsgOfGroup(gNr);
  4069.         ELSE
  4070.           s := dataSys.empty;
  4071.         END;
  4072.       END;
  4073.     ELSE
  4074.       noMore := TRUE
  4075.     END;
  4076.     CatGlobal.busyMouse();
  4077.   END;
  4078.   mtAppl.MouseArrow();
  4079.  
  4080.   ptr^.isLocked := FALSE;
  4081.   IF found THEN
  4082.     IF gNr # ptr^.handle^.group THEN
  4083.       SwitchToNewGroup(gNr, nr, ptr);
  4084.     ELSE
  4085.       SwitchTo(ptr, nr, dJump, FALSE);
  4086.     END;
  4087.     IF suchVar.searchText 
  4088.     THEN
  4089.       IF ~forward
  4090.       THEN
  4091.         v.bool := CatEdit.Search (topWin, suchVar.searchStr[0], EditTypes.fromStart, EditTypes.forward,
  4092.                                   EditTypes.searchOne, 1, suchVar.gross, FALSE, FALSE);
  4093.       ELSE
  4094.         (* Noch im Anzeigeeditor suchen *)
  4095.         v.bool := CatEdit.Search (topWin, suchVar.searchStr[0], EditTypes.fromStart, EditTypes.forward,
  4096.                                   EditTypes.searchOne, 1, suchVar.gross, FALSE, FALSE);
  4097.       END;
  4098.     END;
  4099.     IF suchVar.change & suchVar.ask THEN
  4100.       IF mtAlerts.Alert(1, MTE.changeFlgs) = 1 THEN
  4101.         SETBITS := suchVar.setBits; CLEARBITS := suchVar.clearBits;
  4102.         InternalChange(ptr, newBits);
  4103.       END;
  4104.     END;
  4105.   ELSE
  4106.     (* Nichts gefunden *)
  4107.     CatGlobal.Bing (7);
  4108.   END;
  4109.   isInSearch := FALSE;
  4110. END DoSearch;
  4111.  
  4112. PROCEDURE grinInfoline( msgWin : INTEGER; editWin : INTEGER; REF infoline : ARRAY OF CHAR);
  4113. VAR info,
  4114.     ap      : CatTypes.String255;
  4115.     format  : ARRAY [0..40] OF CHAR;
  4116.     scrap   : ARRAY[0..10] OF CHAR;
  4117.     z, zz,
  4118.     d, l,
  4119.     ll      : CARDINAL;
  4120.     inStr,
  4121.     other   : BOOLEAN;
  4122.     c       : CHAR;
  4123.     ptr     : oneWindowPtr;
  4124.     dt      : ConvertDate.Date;
  4125.     ti      : ConvertDate.Time;
  4126.     sex     : GenderTest.Sex;
  4127.   
  4128.   PROCEDURE GetFormat (REF s: ARRAY OF CHAR; VAR start: CARDINAL; 
  4129.                        VAR form : ARRAY OF CHAR);
  4130.     VAR p : CARDINAL;
  4131.   BEGIN
  4132.     p := MagicStrings.Pos (')', s, start, FALSE);
  4133.     IF p < LENGTH (s)
  4134.     THEN
  4135.       MagicStrings.Copy (s, start, p-start, form);
  4136.       start := p;
  4137.     ELSE
  4138.       MagicStrings.Assign ('', form);
  4139.     END;
  4140.   END GetFormat;
  4141.   
  4142.   PROCEDURE RealName (VAR name: ARRAY OF CHAR);
  4143.   BEGIN
  4144.     WITH ptr^ DO
  4145.       IF MagicStrings.Length (mess.name^) = 0
  4146.       THEN
  4147.         MagicStrings.Assign(mess.Absender^, name);
  4148.         d := MagicStrings.Pos ('@', name, 0, FALSE);
  4149.         IF d < LENGTH (name) THEN
  4150.           name [d] := 0C; DEC (d);
  4151.           WHILE (d>0) & (name[d] = ' ') DO
  4152.             name[d] := 0C;
  4153.             DEC (d);
  4154.           END;
  4155.         END;
  4156.       ELSE
  4157.         MagicStrings.Assign(mess.name^, name)
  4158.       END; 
  4159.     END;
  4160.   END RealName;
  4161.  
  4162.   PROCEDURE SplitName (REF name: ARRAY OF CHAR; VAR firstName, lastName: ARRAY OF CHAR);
  4163.    VAR p, lastP : INTEGER;
  4164.   BEGIN
  4165.     p := 0;
  4166.     lastP := 0;
  4167.     REPEAT 
  4168.       lastP := p;
  4169.       IF p > 0 THEN INC (p); END;
  4170.       p := Strings.Pos (" ", name, p);
  4171.     UNTIL p < 0;
  4172.     Strings.Copy (name, 0, lastP, firstName, v.bool);
  4173.     Strings.Copy (name, lastP+1, INTEGER(LENGTH(name))-lastP-1, lastName, v.bool);
  4174.   END SplitName;
  4175.  
  4176.   PROCEDURE FirstName (VAR name: ARRAY OF CHAR);
  4177.     VAR tmp : ARRAY [0..79] OF CHAR;
  4178.   BEGIN
  4179.     RealName (name);
  4180.     SplitName (name, name, tmp);
  4181.   END FirstName;
  4182.  
  4183.   PROCEDURE LastName (VAR name: ARRAY OF CHAR);
  4184.     VAR tmp : ARRAY [0..79] OF CHAR;
  4185.   BEGIN
  4186.     RealName (name);
  4187.     SplitName (name, tmp, name);
  4188.   END LastName;
  4189.  
  4190. BEGIN
  4191.   IF handlePool.FindEntry(ADR( msgWin), FindWinCond, windows, ptr)
  4192.   THEN
  4193.     WITH ptr^ DO
  4194.       l := MagicStrings.Length(infoline);
  4195.       d := 0;
  4196.       info := '';
  4197.       inStr := FALSE;
  4198.       z := 0; 
  4199.       WHILE z < l DO
  4200.         IF ~inStr THEN
  4201.           ap := '';
  4202.           other := FALSE;
  4203.           CASE MagicStrings.Cap (infoline[z]) OF
  4204.            'U' : MagicStrings.Assign(mess.Absender^, ap) |
  4205.            'D' : IF infoline[z+1] = '('
  4206.                  THEN
  4207.                    (* Mit Format! *)
  4208.                    INC (z,2);
  4209.                    GetFormat (infoline, z, format);
  4210.                    IF format[0] = '#'
  4211.                    THEN
  4212.                      c := format[1];
  4213.                      FOR zz := 0 TO 31 DO
  4214.                        format[zz] := c;
  4215.                      END;
  4216.                      format[32] := 0C;
  4217.                    END;
  4218.                    ConvertDate.CatDate2Datim (mess.tauschDate, dt, ti);
  4219.                    ConvertDate.DayToText (dt, format, ap);
  4220.                  ELSE
  4221.                    MagicStrings.Copy(mess.Datum, 0, 2, ap) 
  4222.                  END; |
  4223.            'T' : IF infoline[z+1] = '('
  4224.                  THEN
  4225.                    INC (z,2);
  4226.                    GetFormat (infoline, z, format);
  4227.                    ConvertDate.CatDate2Datim (mess.tauschDate, dt, ti);
  4228.                    ConvertDate.TimeToText (ti, format, ap);
  4229.                  ELSE
  4230.                    MagicStrings.Copy(mess.Datum, 13, 5, ap)
  4231.                  END; |
  4232.            'A' : IF infoline[z+1] = '('
  4233.                  THEN
  4234.                    INC (z,2);
  4235.                    GetFormat (infoline, z, format);
  4236.                    ConvertDate.CatDate2Datim (mess.tauschDate, dt, ti);
  4237.                    ConvertDate.DateToText (dt, format, ap);
  4238.                  ELSE
  4239.                    MagicStrings.Copy(mess.Datum, 4, 8, ap)
  4240.                  END; |
  4241.            'H' : IF infoline[z+1] = '('
  4242.                  THEN
  4243.                    INC (z,2);
  4244.                    GetFormat (infoline, z, format);
  4245.                  ELSE
  4246.                    MagicStrings.Assign ('G', format);
  4247.                  END;
  4248.                  ConvertDate.CatDate2Datim (mess.tauschDate, dt, ti);
  4249.                  ConvertDate.FuzzyTime (ti, format, ap); |
  4250.            'F' : IF infoline[z+1] = '('
  4251.                  THEN
  4252.                    INC (z,2);
  4253.                    GetFormat (infoline, z, format);
  4254.                  ELSE
  4255.                    MagicStrings.Assign ('G', format);
  4256.                  END;
  4257.                  ConvertDate.CatDate2Datim (mess.tauschDate, dt, ti);
  4258.                  ConvertDate.FuzzyDate (dt, ti, format, ap); |
  4259.            'G' : IF mess.Gruppe # dataSys.private THEN
  4260.                    GroupSelect.GroupName (mess.Gruppe, ap);
  4261.                  ELSIF mess.Gruppe = dataSys.private THEN
  4262.                    MagicStrings.Assign('pers”nliche Msg', ap)
  4263.                  END; |
  4264.            'M' : MagicStrings.Assign(mess.MailID^, ap) |
  4265.            'R' : RealName (ap); |
  4266.            'V' : FirstName (ap); |
  4267.            'N' : LastName (ap); |
  4268.            'S' : FirstName (ap);
  4269.                  GenderTest.SexTest (ap, sex);
  4270.                  IF sex = GenderTest.female
  4271.                  THEN
  4272.                    MagicStrings.Assign (cFemale, ap)
  4273.                  ELSE
  4274.                    MagicStrings.Assign (cMale, ap)
  4275.                  END;
  4276.                  |
  4277.            'I' : IF MagicStrings.Length (mess.mid^) = 0
  4278.                  THEN
  4279.                    MagicStrings.Assign(mess.MailID^, ap)
  4280.                  ELSE
  4281.                    MagicStrings.Assign (mess.mid^, ap)
  4282.                  END; |
  4283.            '"',
  4284.            "'" : inStr := ~inStr;
  4285.                  other := TRUE;
  4286.           ELSE
  4287.             ap[0] := infoline[z];
  4288.             ap[1] := 0C;  
  4289.             other := TRUE;
  4290.           END;
  4291.  
  4292.         ELSE (* IF ~inStr *)
  4293.           IF infoline[z] = '"' THEN
  4294.             inStr := ~inStr;
  4295.             ap := '';
  4296.           ELSIF infoline[z] = "'" THEN
  4297.             inStr := ~inStr;
  4298.             ap := '';
  4299.           ELSE
  4300.             ap[0] := infoline[z]; 
  4301.             ap[1] := 0C;
  4302.           END;
  4303.         END;
  4304.         MagicStrings.Append(ap, info);
  4305.         INC (z);
  4306.       END;
  4307.       MagicStrings.Append(CR, info);
  4308.       MagicStrings.Append(LF, info);
  4309.       IF (MagicStrings.Length(info) > 0) & CatEdit.IsEditTop(editWin) THEN
  4310.         v.bool := CatEdit.QuoteSomething (editWin, '', ADR(info), LENGTH (info), -1);
  4311.       END;
  4312.     END;
  4313.   END;
  4314. END grinInfoline;
  4315.  
  4316. PROCEDURE changeTree(win : INTEGER; clear, set : BITSET; all : BOOLEAN);
  4317. (* Baum mit durchlaufen, dabei die Flags clear l”schen und set setzen   *)
  4318. (* all - ganzer Baum, sonst nur runter                                  *)
  4319. VAR ptr : oneWindowPtr;
  4320. BEGIN
  4321.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) THEN
  4322.     CLEARBITS := clear; SETBITS := set;
  4323.     data.TreeFlags(ptr^.handle^.Zugriff, ptr^.mess.MailNr, all, flagupdate, newBits);
  4324.   END;
  4325. END changeTree;
  4326.  
  4327. (* Fr die Protokolluntersttzung: *)
  4328. (*$? grinWindowProto:
  4329. PROCEDURE getAllWinds(adr : ADDRESS; maxAnz : INTEGER; VAR anz : INTEGER);
  4330. (* Schreibt alle offenen Anzeigefenster in den Speicher ab <adr>    *)
  4331. (* Maximal <max> viele. Rckgabewert der geschriebenen in <anz>.    *)
  4332. (* Sind es mehr als max, so ist dies die Anzahl der offenen Fenster *)
  4333. VAR cp : POINTER TO ARRAY[0..MAX(CARDINAL)] OF INTEGER;
  4334.  
  4335.   (*$A+,Z-*)
  4336.   PROCEDURE scanWinCond(e, i : ADDRESS):BOOLEAN;
  4337.   (* Abbruchprozedur, wie in <Lists> gefordert *)
  4338.   VAR p : oneWindowPtr;
  4339.   BEGIN
  4340.     IF e # NIL THEN
  4341.       p := e;
  4342.       IF anz < maxAnz THEN (* In die Tabelle eintragen, falls es noch pažt *)
  4343.         cp^[anz] := p^.win;
  4344.       END;
  4345.       INC(anz);
  4346.     END;
  4347.     RETURN FALSE
  4348.   END scanWinCond;
  4349.   (*$A=,Z=*)
  4350.  
  4351. BEGIN
  4352.   anz := 0;
  4353.   cp  := adr;
  4354.   Lists.ResetList(windows);
  4355.   Lists.ScanEntries(windows, Lists.forward, scanWinCond, NIL, v.bool);
  4356. END getAllWinds;
  4357.  
  4358. PROCEDURE getPos(adr : ADDRESS; pos : INTEGER; win : INTEGER):CARDINAL;
  4359. (* Positionen zu einem Fenster abrufen: *)
  4360. (* 0 Neue, 1 letzte Position, 2 ab Datum, 3 ab Nummer, 4 erste ungelesene *)
  4361. (* bei 2 und 3 wird in adr die Adresse eines Strings bergeben.           *)
  4362. VAR ptr : oneWindowPtr;
  4363.     str : CatTypes.Str1023Ptr;
  4364. BEGIN
  4365.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) THEN
  4366.     str := adr;
  4367.     CASE pos OF
  4368.       0 : RETURN data.FirstNewMsg(ptr^.mess.Gruppe);
  4369.     | 1 : RETURN data.lastReadMsgOfGroup(ptr^.mess.Gruppe);
  4370.     | 2 : RETURN data.NumberOfID(ptr^.handle^.Zugriff, str^);
  4371.     | 3 : RETURN data.NumberOfDate(ptr^.handle^.Zugriff, ConvertDate.StrToDate(str^));
  4372.     | 4 : RETURN data.unreadMsgPos(ptr^.mess.Gruppe);
  4373.     ELSE
  4374.       RETURN 0FFFFH;
  4375.     END;
  4376.   ELSE
  4377.     RETURN 0FFFFH;
  4378.   END;
  4379. END getPos;
  4380.  
  4381. PROCEDURE switchMess(win : INTEGER; mess, group : CARDINAL):BOOLEAN;
  4382. (* Neue Msg in ein Fenster setzen; Fr das Protokoll *)
  4383. VAR ptr : oneWindowPtr;
  4384. BEGIN
  4385.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) THEN
  4386.     msgList.listUnlockWdw (ptr^.listHdl);
  4387.     ptr^.listHdl := 0;
  4388.     IF ptr^.mess.Gruppe = group THEN
  4389.       SwitchTo (ptr, mess, dJump, FALSE);
  4390.     ELSE
  4391.       SwitchToNewGroup(group, mess, ptr);
  4392.     END;
  4393.     RETURN TRUE;
  4394.   ELSE
  4395.     RETURN FALSE;
  4396.   END;
  4397. END switchMess;
  4398.  
  4399. PROCEDURE getInfo(win : INTEGER; adr : ADDRESS; amount : LONGCARD):BOOLEAN;
  4400. (* Die Infos zu diesem Fenster abholen. Geliefert wird:                             *)
  4401. (* ab <adr> steht ein data.MessageType. Direkt dahinter die Infostrings und         *)
  4402. (* dahinter noch der eigentliche MsgText. Gibt zurck, ob es geklappt hat oder ob   *)
  4403. (* das Fenster nicht mehr da ist bzw. die Information nicht gepažt hat.             *)
  4404. (* --- Ende der Protokollprozeduren --- *)
  4405. VAR ptr : oneWindowPtr;
  4406.     a   : ADDRESS;
  4407.     m   : POINTER TO data.MessageType;
  4408.     pLC : POINTER TO LONGCARD;
  4409.         
  4410. BEGIN
  4411.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) THEN
  4412.     IF amount = 0
  4413.     THEN
  4414.       pLC := adr;
  4415.       amount := pLC^;
  4416.       INC (adr, 4);
  4417.       IF amount = 0
  4418.       THEN
  4419.         RETURN FALSE
  4420.       END;
  4421.     END;
  4422.     IF amount >= TSIZE(data.MessageType) + LONG(ptr^.mess.textLen) + LONG(ptr^.mess.infoLen) THEN
  4423.       m  := adr;
  4424.       m^ := ptr^.mess;
  4425.       a  := adr + TSIZE(data.MessageType);
  4426.       IF ODD(LONGCARD(a)) THEN INC(a) END;
  4427.       Block.Copy(ptr^.mess.InfoStrings, LONG(ptr^.mess.infoLen), a);
  4428.       m^.InfoStrings := a;
  4429.      WITH m^ DO      
  4430.       IF (LONGCARD(MailID) >= LONGCARD(ptr^.mess.InfoStrings)) &
  4431.          (LONGCARD(MailID) <= LONGCARD(ptr^.mess.InfoStrings)+LONG(ptr^.mess.infoLen)) THEN
  4432.         MailID := ADDRESS(LONGCARD(MailID)-LONGCARD(ptr^.mess.InfoStrings)+LONGCARD(a));
  4433.       ELSE
  4434.         MailID := ADDRESS(0);
  4435.       END;
  4436.       IF (LONGCARD(Betreff) >= LONGCARD(ptr^.mess.InfoStrings)) &
  4437.          (LONGCARD(Betreff) <= LONGCARD(ptr^.mess.InfoStrings)+LONG(ptr^.mess.infoLen)) THEN
  4438.         Betreff := ADDRESS(LONGCARD(Betreff)-LONGCARD(ptr^.mess.InfoStrings)+LONGCARD(a));
  4439.       ELSE
  4440.         Betreff := ADDRESS(0);
  4441.       END;
  4442.       IF (LONGCARD(Absender) >= LONGCARD(ptr^.mess.InfoStrings)) &
  4443.          (LONGCARD(Absender) <= LONGCARD(ptr^.mess.InfoStrings)+LONG(ptr^.mess.infoLen)) THEN
  4444.         Absender := ADDRESS(LONGCARD(Absender)-LONGCARD(ptr^.mess.InfoStrings)+LONGCARD(a));
  4445.       ELSE
  4446.         Absender := ADDRESS(0);
  4447.       END;
  4448.       IF (LONGCARD(Empfaenger) >= LONGCARD(ptr^.mess.InfoStrings)) &
  4449.          (LONGCARD(Empfaenger) <= LONGCARD(ptr^.mess.InfoStrings)+LONG(ptr^.mess.infoLen)) THEN
  4450.         Empfaenger := ADDRESS(LONGCARD(Empfaenger)-LONGCARD(ptr^.mess.InfoStrings)+LONGCARD(a));
  4451.       ELSE
  4452.         Empfaenger := ADDRESS(0);
  4453.       END;
  4454.       IF (LONGCARD(mid) >= LONGCARD(ptr^.mess.InfoStrings)) &
  4455.          (LONGCARD(mid) <= LONGCARD(ptr^.mess.InfoStrings)+LONG(ptr^.mess.infoLen)) THEN
  4456.         mid := ADDRESS(LONGCARD(mid)-LONGCARD(ptr^.mess.InfoStrings)+LONGCARD(a));
  4457.       ELSE
  4458.         mid := ADDRESS(0);
  4459.       END;
  4460.       IF (LONGCARD(rid) >= LONGCARD(ptr^.mess.InfoStrings)) &
  4461.          (LONGCARD(rid) <= LONGCARD(ptr^.mess.InfoStrings)+LONG(ptr^.mess.infoLen)) THEN
  4462.         rid := ADDRESS(LONGCARD(rid)-LONGCARD(ptr^.mess.InfoStrings)+LONGCARD(a));
  4463.       ELSE
  4464.         rid := ADDRESS(0);
  4465.       END;
  4466.       IF (LONGCARD(box) >= LONGCARD(ptr^.mess.InfoStrings)) &
  4467.          (LONGCARD(box) <= LONGCARD(ptr^.mess.InfoStrings)+LONG(ptr^.mess.infoLen)) THEN
  4468.         box := ADDRESS(LONGCARD(box)-LONGCARD(ptr^.mess.InfoStrings)+LONGCARD(a));
  4469.       ELSE
  4470.         box := ADDRESS(0);
  4471.       END;
  4472.       IF (LONGCARD(name) >= LONGCARD(ptr^.mess.InfoStrings)) &
  4473.          (LONGCARD(name) <= LONGCARD(ptr^.mess.InfoStrings)+LONG(ptr^.mess.infoLen)) THEN
  4474.         name := ADDRESS(LONGCARD(name)-LONGCARD(ptr^.mess.InfoStrings)+LONGCARD(a));
  4475.       ELSE
  4476.         name := ADDRESS(0);
  4477.       END;
  4478.       IF (LONGCARD(gate) >= LONGCARD(ptr^.mess.InfoStrings)) &
  4479.          (LONGCARD(gate) <= LONGCARD(ptr^.mess.InfoStrings)+LONG(ptr^.mess.infoLen)) THEN
  4480.         gate := ADDRESS(LONGCARD(gate)-LONGCARD(ptr^.mess.InfoStrings)+LONGCARD(a));
  4481.       ELSE
  4482.         gate := ADDRESS(0);
  4483.       END;
  4484.       IF (LONGCARD(mime) >= LONGCARD(ptr^.mess.InfoStrings)) &
  4485.          (LONGCARD(mime) <= LONGCARD(ptr^.mess.InfoStrings)+LONG(ptr^.mess.infoLen)) THEN
  4486.         mime := ADDRESS(LONGCARD(mime)-LONGCARD(ptr^.mess.InfoStrings)+LONGCARD(a));
  4487.       ELSE
  4488.         mime := ADDRESS(0);
  4489.       END;
  4490.      END;
  4491.       a := a + LONG(m^.infoLen);
  4492.       IF ODD(LONGCARD(a)) THEN INC(a) END;
  4493.       IF LONG(ptr^.mess.textLen) <= amount - (LONGCARD(a)-LONGCARD(adr)) THEN
  4494.         data.ReadText(ptr^.handle^.Zugriff, ptr^.mess.MailNr, a);
  4495.         IF data.error # data.noError THEN RETURN FALSE END;
  4496.       END;
  4497.       m^.Text := a;
  4498.       RETURN TRUE;
  4499.     ELSE
  4500.       RETURN FALSE;
  4501.     END;
  4502.   ELSE
  4503.     RETURN FALSE;
  4504.   END;
  4505. END getInfo;
  4506. *)
  4507.  
  4508. PROCEDURE getBasicInfo(win : INTEGER; VAR group, mess: CARDINAL; storageAmount : LONGCARD):BOOLEAN;
  4509. (* Feststellen, welche Msg welcher Gruppe im bergebenen Fenster dargestellt wird.  *)
  4510. (* In StorageAmount wird zurckgegeben, wieviel Speicher mal ben”tigt, um die       *)
  4511. (* Informationen, die zu dieser Msg geh”ren, zu speichern.                          *)
  4512. VAR ptr : oneWindowPtr;
  4513. BEGIN
  4514.   IF handlePool.FindEntry(ADR(win), FindWinCond, windows, ptr) THEN
  4515.     group := ptr^.mess.Gruppe;
  4516.     mess  := ptr^.mess.MailNr;
  4517.     storageAmount := TSIZE(data.MessageType) + LONG(ptr^.mess.textLen) + LONG(ptr^.mess.infoLen) + 200;
  4518.     RETURN TRUE;
  4519.   ELSE
  4520.     RETURN FALSE;
  4521.   END;
  4522. END getBasicInfo;
  4523.  
  4524. PROCEDURE grinOnlyOneWind (VAR wdw: INTEGER): BOOLEAN;
  4525. (* Wenn nur ein grin-Window offen ist, bekommt man TRUE zurck und 
  4526.  * das wdw-Handle auch direkt
  4527.  *)
  4528.   VAR p : oneWindowPtr;
  4529. BEGIN
  4530.   wdw := -1;
  4531.   IF Lists.NoOfEntries (windows) = 1
  4532.   THEN
  4533.     Lists.ResetList(windows);
  4534.     p := Lists.NextEntry (windows);
  4535.     IF p # NIL THEN 
  4536.       wdw := p^.win;
  4537.       RETURN TRUE;
  4538.     END;
  4539.   END;
  4540.   RETURN FALSE;
  4541. END grinOnlyOneWind;
  4542.  
  4543. (*$Z+*)
  4544. PROCEDURE testGrinWdw (wdw: INTEGER) : BOOLEAN;
  4545.   VAR ptr : oneWindowPtr;
  4546.       res: BOOLEAN;
  4547. BEGIN
  4548.   res := handlePool.FindEntry(ADR(wdw), FindWinCond, windows, ptr);
  4549.   RETURN res;
  4550. END testGrinWdw;
  4551. (*$Z=*)
  4552.  
  4553. PROCEDURE GetGrinTopWdw (VAR wdw: INTEGER);
  4554. (* Liefert das oberste Anzeigefenster zurck *)
  4555. BEGIN
  4556.   wdw := WdwManager.FindSpecialTop (testGrinWdw);
  4557. END GetGrinTopWdw;
  4558.  
  4559. BEGIN
  4560.   Lists.CreateList(windows, v.bool);
  4561.   globalNumber := -1;
  4562.   isInSearch := FALSE;
  4563. END grin.
  4564.